SpringBean-生命周期

Spirng Bean 元信息配置阶段

1 面向资源

  • xml配置(很熟悉了不做讨论)
  • Properties配置
public class BeanMetaDemo {public static void main(String[] args) {DefaultListableBeanFactory factory = new DefaultListableBeanFactory();PropertiesBeanDefinitionReader reader = new PropertiesBeanDefinitionReader(factory);Resource resource = new ClassPathResource("/meta-info/person.properties");// 解决乱码的问题EncodedResource encodedResource = new EncodedResource(resource, "UTF-8");int i = reader.loadBeanDefinitions(encodedResource);Object person = factory.getBean("person");System.out.println(person);}
}
person.(class)=pojo.Person
person.id=10010
person.name=李勇

2 面向注解
3 面向API

Bean 元信息解析

1 面向资源BeanDefiniton 解析

  • BeanDefinitonReader
  • xml 解析器 BeanDefinitionParser
    2 面向注解BeanDefiniton
  • AnnotatedBeanDefinitonReader
// 基于注解的APIBean注册
public class AnnotatedBeanDefinitionParsingDemo {public static void main(String[] args) {DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(beanFactory);int beforeCount = beanFactory.getBeanDefinitionCount();reader.register(AnnotatedBeanDefinitionParsingDemo.class);int afterCount = beanFactory.getBeanDefinitionCount();System.out.println(afterCount - beforeCount);AnnotatedBeanDefinitionParsingDemo bean = beanFactory.getBean(AnnotatedBeanDefinitionParsingDemo.class);System.out.println(bean);}

Bean注册阶段

BeanDefinitionregistery

@Overridepublic void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException {Assert.hasText(beanName, "Bean name must not be empty");Assert.notNull(beanDefinition, "BeanDefinition must not be null");if (beanDefinition instanceof AbstractBeanDefinition) {try {((AbstractBeanDefinition) beanDefinition).validate();}catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,"Validation of bean definition failed", ex);}}BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);if (existingDefinition != null) {if (!isAllowBeanDefinitionOverriding()) {throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);}else if (existingDefinition.getRole() < beanDefinition.getRole()) {// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTUREif (logger.isInfoEnabled()) {logger.info("Overriding user-defined bean definition for bean '" + beanName +"' with a framework-generated bean definition: replacing [" +existingDefinition + "] with [" + beanDefinition + "]");}}else if (!beanDefinition.equals(existingDefinition)) {if (logger.isDebugEnabled()) {logger.debug("Overriding bean definition for bean '" + beanName +"' with a different definition: replacing [" + existingDefinition +"] with [" + beanDefinition + "]");}}else {if (logger.isTraceEnabled()) {logger.trace("Overriding bean definition for bean '" + beanName +"' with an equivalent definition: replacing [" + existingDefinition +"] with [" + beanDefinition + "]");}}this.beanDefinitionMap.put(beanName, beanDefinition);}else {// 线程安全if (hasBeanCreationStarted()) {// Cannot modify startup-time collection elements anymore (for stable iteration)synchronized (this.beanDefinitionMap) {this.beanDefinitionMap.put(beanName, beanDefinition);List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);// 保证顺序updatedDefinitions.addAll(this.beanDefinitionNames);updatedDefinitions.add(beanName);this.beanDefinitionNames = updatedDefinitions;removeManualSingletonName(beanName);}}else {// Still in startup registration phasethis.beanDefinitionMap.put(beanName, beanDefinition);this.beanDefinitionNames.add(beanName);removeManualSingletonName(beanName);}this.frozenBeanDefinitionNames = null;}if (existingDefinition != null || containsSingleton(beanName)) {resetBeanDefinition(beanName);}}

BeanDefinition 合并阶段

BeanDefinition#getParentName
在这里插入图片描述
在xml里面是通过这个属性来配置的,所以需要classloader的参与:
在这里插入图片描述

在注解其实本身就包含了继承关系,可以直接拿到父类信息。

1 没有父类了已经RootBeanDefinition 不需要合并
2 普通的BeanDefinition为GenericBeanDefinition需要合并
合并过程中GenericBeanDefinition->RootBeanDefinition
在这里插入图片描述

代码贴士:ConcurrentHashMap虽然是线程安全的但是只针对于单个操作,get和put,如果有多个get,put操作一起也不能保证是线程安全的。

Bean Class 加载

这里返回的是一个文本BeanDefinition#getBeanClassName
在这里插入图片描述AbstractAutowireCapableBeanFactory#createBean
在这里插入图片描述
org.springframework.beans.factory.support.AbstractBeanDefinition#resolveBeanClass

在这里插入图片描述

this.beanClass 之前是字符串类型,在处理完毕以后是Class类型。

Bean实例化前阶段

InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
通常用于替换之前的实现类,绕开Spring的实例化。

public class BeanInstantiationLifeCycleDemo {@Beanpublic Person person() {Person person = new Person();person.setName("liyong");person.setId(11L);return person;}public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();context.register(BeanInstantiationLifeCycleDemo.class);DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getBeanFactory();beanFactory.addBeanPostProcessor(new MyPostProcessBeforeInstantiation());context.refresh();Object person = context.getBean("person");System.out.println(person);}static class MyPostProcessBeforeInstantiation implements InstantiationAwareBeanPostProcessor {@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {// 实例化之前执行 如果说满足条件直接替换之前的实现if (ObjectUtils.nullSafeEquals("person", beanName) && Person.class.equals(beanClass)) {Person person = new Person();person.setId(11L);person.setName("person");return person;}return null;}}
}

在这里我们返回了我们创建的对象,所以后面的操作不再进行了:
在这里插入图片描述

Spring Bean 实例化阶段

实例化方式

  • 传统方式
  • 实例化策略InstantitaionStrategy
    构造器依赖注入

InstantitaionStrategy有两种实现方法
1 传统的实现方法
AbstractAutowireCapableBeanFactory#createBeanInstance
在这里插入图片描述

2 特殊的实现方法

Spring Bean 实例化后阶段

这里控制了对象实例化以后是否对属性进行赋值:
InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation

@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {// 这里就可以注入我们自己的值,这里和前面before的区别就是 这里我们对象已经被创建了,我们是在已经创建好的对象给它改变属性值if (ObjectUtils.nullSafeEquals("person", beanName) && Person.class.equals(bean.getClass())) {Person person = (Person) bean; person.setId(11L);person.setName("person");return false;}return true;
}

在这里插入图片描述
在这里我们返回了false,所以后面操作不会执行了,而后面的操作也就是赋值属性。

Spring Bean 属性赋值前阶段

Bean 属性值元信息

  • PropertyValues

Bean属性值前回调

  • InstantiationAwareBeanPostProcessor#postProcessPropertyValues 注意到在高版本的Spring 这个方法已经被打上了过时的标签
  • InstantiationAwareBeanPostProcessor#postProcessProperties (5.1及以后)

如果我们希望拦截属性赋值操作

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {// 这里就可以注入我们自己的值 需要注意如果我们postProcessAfterInstantiation 已经返回了false这里就不会执行if (ObjectUtils.nullSafeEquals("person", beanName) && Person.class.equals(bean.getClass())) {MutablePropertyValues propertyValues = new MutablePropertyValues();propertyValues.add("number", "1111");return propertyValues;}return pvs;
}

Spring 生命周期 Aware 接口的顺序

其实顺序就是下面这个顺序:
在这里插入图片描述
我们可以看到源码中的调用顺序:
在这里插入图片描述
EnvironmentAware 以及后面的接口都是属于ApplicationContext的生命周期,普通的BeanFactory 并不会回调这些Aware接口,在操作ApplicationContext的时候才会回调这些接口,因为在ApplicationContext初始化阶段,会添加一个AwarePostProcessor但是这个类是内置类,所以只有与ApplicationContext打交道才会有更多的Aware接口方法回调。

SpirngBean初始化 前阶段

在前面的讨论,已经完成了以下工作,这些工作也是属于前阶段
在这里插入图片描述
InstantiationAwareBeanPostProcessor#postProcessBeforeInitialization

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {}

源码是在这里进行应用的:
在这里插入图片描述

AbstractApplicationContext#prepareBeanFactory
在这里插入图片描述

SpringBean 初始化阶段

他们的执行顺序就是下面的执行顺序
在这里插入图片描述
@PostConstruct 是依赖于注解驱动的,如果通过xml的方式是不会触发的,因为没有对应的PostProcessor。如果我们需要这个生效

beanFactory.addBeanPostProcessor(new CommonAnnotationPostProcessor());

自定义方法是通过xml init-method来进行配置。
AbstractAutowireCapableBeanFactory#initializeBean
实际上PostConstruct是在这个方法applyBeanPostProcessorsBeforeInitialization进行触发的
在这里插入图片描述

初始化后阶段

BeanPostProcessor#postProcessAfterInitialization

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {return InstantiationAwareBeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}

初始化完成阶段

通过下面这个接口来实现
在这里插入图片描述
preInstantiateSingletons在这个方法里面被调用,他通常需要在ApplicationContext来进行使用,需要显式的调用。确保Bean已经被完全初始化。
在这里插入图片描述

Spring Bean销毁阶段

在这里插入图片描述
DisposableBeanAdapter#destroy()
销毁前:
DestructionAwareBeanPostProcessor

@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
}
beanFactory.addBeanPostProcessor(new MyDestructionAwareBeanPostProcessor());
// 这个销毁是在容器中销毁 而不是在Java 中销毁
beanFactory.destoryBean("person", person);

Spring销毁阶段

有这样几种方式
在这里插入图片描述

Spirng Bean垃圾回收

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/839575.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Java面试】三、Redis篇(下)

文章目录 1、抢券场景2、Redis分布式锁3、Redisson实现分布式锁4、Redisson实现的分布式锁是可重入锁5、Redisson实现分布式锁下的主从一致性6、面试 1、抢券场景 正常思路&#xff1a; 代码实现&#xff1a; 比如优惠券数量为1。正常情况下&#xff1a;用户A的请求过来&a…

DeepRec Extension 打造稳定高效的分布式训练

DeepRec Extension 即 DeepRec 扩展&#xff0c;在 DeepRec 训练推理框架之上&#xff0c;围绕大规模稀疏模型分布式训练&#xff0c;我们从训练任务的视角提出了自动弹性训练&#xff0c;分布式容错等功能&#xff0c;进一步提升稀疏模型训练的整体效率&#xff0c;助力 DeepR…

开源RAG,本地mac启动 dify源码服务

一、Dify文档 参考官方文档来操作&#xff0c;基本没太大的问题。一些细节&#xff0c;我在本篇文章中补充了出来。 这篇文章主要讲以源码的方式启动后端服务&#xff0c;前端服务使用容器启动。 dify 文档地址 欢迎使用 Dify | 中文 | Dify Dify 本地源码部署文档&#xff…

如何解读伊朗发布的直升机事故调查报告?一般事故调查报告应怎么写?

如何解读伊朗发布的直升机事故调查报告&#xff1f;一般事故调查报告应怎么写&#xff1f; 据央视新闻客户端消息&#xff1a;当地时间5月23日&#xff0c;伊朗武装部队总参谋部发布首份已故总统莱希及其随行人员乘坐的直升机事故调查报告。以下是#李秘书讲写作#对报告内容的解…

基于微信的家庭理财管理小程序的设计与实现(论文+源码)_kaic

摘 要 随着中国经济的飞速发展&#xff0c;家庭收入不断增高&#xff0c;人们的消费除了简单的维持日常生活之外&#xff0c;还有其他的消费方式&#xff0c;比如旅游、电商购物等&#xff0c;层出不穷的消费方式带给人快乐的同时&#xff0c;也常常让一些人逐渐无法把握住自…

【LeetCode】每日一题 2024_5_24 找出最具竞争力的子序列(栈,模拟,贪心)

文章目录 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01;题目&#xff1a;找出最具竞争力的子序列题目描述代码与解题思路 每天进步一点点 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01; 题目&#xff1a;找出最具竞争力的子序列 题目链接&a…

广义线性chirplet变换【附MATLAB代码】

文章来源&#xff1a;微信公众号&#xff1a;EW Frontier 摘要 时频分析方法是一种刻画信号时变特征的有效工具&#xff0c;在相当长的一段时间内受到了广泛的关注。随着TF算法的发展&#xff0c;许多先进的方法被提出&#xff0c;可以提供更精确的TF结果。但是&#xff0c;不…

【LabVIEW FPGA入门】使用事件发生函数同步FPGA循环

1.使用事件发生函数 使用 Occurrences 函数来控制单独的同步活动。特别是&#xff0c;当您希望程序框图的一部分等待程序框图的另一部分完成任务而不强制 LabVIEW 进行轮询时&#xff0c;请使用这些函数。 您可以使用全局变量执行类似于occurrences函数的功能&#xff0c;通过一…

详解CSS(二)

目录 1.背景属性 1.1背景颜色 1.2背景图片 1.3背景平铺 1.4背景位置 1.5背景尺寸 2.圆角矩形 3.元素的显示模式 3.1行内元素/内联元素&#xff08;Inline element&#xff09; 3.2块级元素&#xff08;Block-level element&#xff09; 3.3行内块元素&#xff08;In…

【leetcode面试经典150题】-80. 删除有序数组中的重复项 II

【leetcode面试经典150题】-80. 删除有序数组中的重复项 II 1 题目介绍2 个人解题思路2.1 代码2.2 思路 3 官方题解 1 题目介绍 给你一个有序数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使得出现次数超过两次的元素只出现两次 &#xff0c;返回删除后数组…

d20(184-190)-勇敢开始Java,咖啡拯救人生

目录 网络通信 网络通信三要素&#xff08;IP地址&#xff0c;端口号&#xff0c;协议 IP地址 InetAddress 端口号 协议 传输层的两个通信协议 UDP通信 java.net.Datagramsocket类 客户端 服务端 UDP通信多收多发 客户端 服务端 TCP通信 java.net.Socket类 客…

【全网最全】2024电工杯数学建模A题21页初步参考论文+py代码+保奖思路等(后续会更新)

您的点赞收藏是我继续更新的最大动力&#xff01; 一定要点击如下的卡片链接&#xff0c;那是获取资料的入口&#xff01; 【全网最全】2024电工杯数学建模A题21页初步参考论文py代码保奖思路等&#xff08;后续会更新成品论文&#xff09;「首先来看看目前已有的资料&#x…

企业应考虑的优秀云安全措施

作为云客户&#xff0c;企业有责任确保正确使用他们提供的工具来保证数据和应用程序的安全。让德迅云安全来跟大家一起研究一些典型企业应该考虑的优秀云安全措施。 在数据安全和隐私方面&#xff0c;企业是否在努力跟上疫情的发展?企业不是一个人。就像多年以前&#xff0c;C…

解决小皮面版搭建php网站数据库连接不了

首先进入mysql bin目录下 并执行cmd mysql -u root -pCREATE USER userlocalhost IDENTIFIED BY pass;GRANT ALL PRIVILEGES ON *.* TO userlocalhost;GRANT SELECT, INSERT, UPDATE ON database_name.* TO xxwlocalhost;FLUSH PRIVILEGES;select host ,user from mysql.user…

DOS学习-目录与文件应用操作经典案例-del

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一.前言 二.使用 三.案例 一.前言 DOS系统的del命令是一个用于删除文件的命令行工具。以下…

使用公共Wi-Fi所面临的风险有哪些

尽量不要使用公共wifi做转账、支付、修改密码等金融性或私密性的操作。公共Wi-Fi网络存在许多风险。尽管商家可能认为他们为顾客提供了一个有价值的服务&#xff0c;很多人也认为在星巴克噼里啪啦的乱敲键盘非常小资&#xff0c;但其实这些网络的安全性可能存在极大的漏洞&…

51打开工程,发现cannot read project file问题

解决办法&#xff1a; 1、路径太长&#xff0c;可以在桌面重新创建一个文件夹&#xff0c;把所有的文件都移动到新的文件夹中 2、创建工程的时候&#xff0c;都勾选上&#xff0c;就没问题

OracleDG原理

一、DataGuard架构介绍 1、基本介绍 在DG环境中&#xff0c;至少会有两个数据库&#xff0c;一个数据库处于Open状态&#xff0c;对外提供服务&#xff0c;这个数据库叫做primary Database。第二个数据库处于恢复状态&#xff0c;叫做Standby Database。运行时Primay Databas…

vue从入门到精通(四):MVVM模型

一,MVVM MVVM&#xff08;Model–view–viewmodel&#xff09;是一种软件架构模式。MVVM有助于将图形用户界面的开发与业务逻辑或后端逻辑&#xff08;数据模型&#xff09;的开发分离开来。详见MVVM 二,Vue中的MVVM Vue虽然没有完全遵循 MVVM 模型&#xff0c;但是 Vue 的设…

手机相册怎么恢复?如何挽救误删的照片?

手机相册成为我们存储和分享照片的主要途径&#xff0c;这些照片可能代表着我们的美好回忆、重要时刻或珍贵的瞬间。然而&#xff0c;有时候我们会因为误操作或一时冲动&#xff0c;将一些珍贵的照片误删&#xff0c;并且很难找回来。手机相册怎么恢复呢&#xff1f;本文将为你…