Spring bean的生命周期 解决循环依赖
1. bean的生命周期
- Bean容器在配置文件中找到Spring Bean的定义。
- Bean容器使用Java Reflection API创建Bean的实例。
- 如果声明了任何属性,声明的属性会被设置。如果属性本身是Bean,则将对其进行解析和设置。
- 如果Bean类实现
BeanNameAware
接口,则将通过传递Bean的名称来调用setBeanName()
方法。 - 如果Bean类实现
BeanClassLoaderAware
接口,则将通过传递加载此Bean的ClassLoader对象的实例来调用setBeanClassLoader()
方法。 - 如果Bean类实现
BeanFactoryAware
接口,则将通过传递BeanFactory对象的实例来调用setBeanFactory()
方法。 - 如果有任何与BeanFactory关联的BeanPostProcessors对象已加载Bean,则将在设置Bean属性之前调用
postProcessBeforeInitialization()
方法。 - 如果Bean类实现了
InitializingBean
接口,则在设置了配置文件中定义的所有Bean属性后,将调用afterPropertiesSet()
方法。 - 如果配置文件中的Bean定义包含
init-method
属性,则该属性的值将解析为Bean类中的方法名称,并将调用该方法。 - 如果为Bean Factory对象附加了任何Bean 后置处理器,则将调用
postProcessAfterInitialization()
方法。 - 如果Bean类实现
DisposableBean
接口,则当Application不再需要Bean引用时,将调用destroy()
方法。 - 如果配置文件中的Bean定义包含
destroy-method
属性,那么将调用Bean类中的相应方法定义。
1.spring 的生命周期粗粒度的可以分为4个阶段
第一阶段:实例化(Instantiation)
//实例化是指Bean 从Bean到Object
Object wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
第二阶段: 属性赋值
第三阶段:初始化(Initialization)
初始化前: org.springFrameWork.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization
初始化中 org.springFrameWork.bean.InitializingBean#afterPropertiesSet
初始化后org.springFrameWork.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization
第四阶段:销毁
org.springFrameWork.bean.factory.DisposableBean#destory
https://blog.csdn.net/qq_36975405/article/details/81871774
2. 如何解决循环依赖的问题
什么是循环依赖?
https://blog.csdn.net/qq_36381855/article/details/79752689
https://baijiahao.baidu.com/s?id=1661554759252546253&wfr=spider&for=pc
三级缓存
一级缓存:singletonObjects,存放完全实例化属性赋值完成的Bean,直接可以使用。
二级缓存:earlySingletonObjects,存放早期Bean的引用,尚未属性装配的Bean
三级缓存:singletonFactories,三级缓存,存放实例化完成的Bean工厂。
https://www.jianshu.com/p/8bb67ca11831
1.spirng循环依赖解决
https://baijiahao.baidu.com/s?id=1661554759252546253&wfr=spider&for=pc
https://blog.csdn.net/qq_36381855/article/details/79752689
https://www.cnblogs.com/zzq6032010/p/11406405.html
属性注入主要是在populateBean方法中进行的。对于循环依赖,以我们上文中的Teacher中注入了Student、Student中注入了Teacher为例来说明,假定Spring的加载顺序为先加载Teacher,再加载Student。
getBean方法触发Teacher的初始化后:
a. 首先走到3中的方法1),此时map中都为空,获取不到实例;
b. 然后走到方法2)中,步骤A、步骤C、步骤D为控制map中数据的方法,实现简单,可暂不关注。其中步骤B的getObject方法触发对方法3)的调用;
c. 在方法3)中,先通过createBeanInstance实例化Teacher对象,又将该实例化的对象通过addSingletonFactory方法放入singletonFactories中,完成Teacher对象早期的暴露;
d. 然后在方法3)中通过populateBean方法对Teacher对象进行属性的注入,发现它有一个Student属性,则触发getBean方法对Student进行初始化
e. 重复a、b、c步骤,只是此时要初始化的是Student对象
f. 走到d的时候,调用populateBean对Student对象进行属性注入,发现它有一个Teacher属性,则触发getBean方法对Teacher进行初始化;
g. 对Teacher进行初始化,又来到a,但此时map已经不为空了,因为之前在c步骤中已经将Teacher实例放入了singletonFactories中,a中得到Teacher实例后返回;
h.完成f中对Student的初始化,继而依次往上回溯完成Teacher的初始化;
完成Teacher的初始化后,Student的初始化就简单了,因为map中已经存了这个单例。
至此,Spring循环依赖的总结分析结束,一句话来概括一下:Spring通过将实例化后的对象提前暴露给Spring容器中的singletonFactories,解决了循环依赖的问题。
https://www.jianshu.com/p/8bb67ca11831
参考资料
https://blog.csdn.net/qq_23473123/article/details/76610052
https://zhihu.com/question/38597960
https://zhuanlan.zhihu.com/p/29344811
重点