Spring bean的生命周期 解决循环依赖

1. bean的生命周期

  1. Bean容器在配置文件中找到Spring Bean的定义。
  2. Bean容器使用Java Reflection API创建Bean的实例。
  3. 如果声明了任何属性,声明的属性会被设置。如果属性本身是Bean,则将对其进行解析和设置。
  4. 如果Bean类实现BeanNameAware接口,则将通过传递Bean的名称来调用setBeanName()方法。
  5. 如果Bean类实现BeanClassLoaderAware接口,则将通过传递加载此Bean的ClassLoader对象的实例来调用setBeanClassLoader()方法。
  6. 如果Bean类实现BeanFactoryAware接口,则将通过传递BeanFactory对象的实例来调用setBeanFactory()方法。
  7. 如果有任何与BeanFactory关联的BeanPostProcessors对象已加载Bean,则将在设置Bean属性之前调用postProcessBeforeInitialization()方法。
  8. 如果Bean类实现了InitializingBean接口,则在设置了配置文件中定义的所有Bean属性后,将调用afterPropertiesSet()方法。
  9. 如果配置文件中的Bean定义包含init-method属性,则该属性的值将解析为Bean类中的方法名称,并将调用该方法。
  10. 如果为Bean Factory对象附加了任何Bean 后置处理器,则将调用postProcessAfterInitialization()方法。
  11. 如果Bean类实现DisposableBean接口,则当Application不再需要Bean引用时,将调用destroy()方法。
  12. 如果配置文件中的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

img

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

img

参考资料

https://blog.csdn.net/qq_23473123/article/details/76610052

https://zhihu.com/question/38597960

https://zhuanlan.zhihu.com/p/29344811

重点

https://www.cnblogs.com/ITtangtang/p/3978349.html

https://juejin.cn/post/6857357127406043143

posted @ 2022-07-20 23:20  qtyanan  阅读(84)  评论(0编辑  收藏  举报