Spring循环依赖三级缓存解析。
Spring循环依赖使用场景
- 对象A的构造方法中依赖了B的实例对象, 同时B的field或者setter需要A的实例对象
- 对象A的某个field或者setter依赖了B的实例对象,同时B的某个field或者setter依赖了A的实例对象
(不能解决的使用场景) 3. 对象A的构造函数依赖了B的实例对象,B的构造函数依赖了A的实例对象
Spring单体对象初始化的流程
- createBeanInstance 实例化,仅仅调用对应的构造方法,没有传入指定的sping.xml
- populate populateBean 填充属性,对spring.xml指定的property进行populate
- initializeBean 调用spring.xml中指定的init方法,或者AfterPropertiesSet方法
Spring循环依赖的三级缓存
DefaultSingletonBeanRegistry中的三级缓存:
1 | // 存放初始化好的可以直接使用的bean,单例对象的cache - 一级缓存 |
1 | protected Object getSingleton(String beanName, boolean allowEarlyReference) { |
三级缓存的作用
二级缓存的存在有两个作用
1.三级缓存中获取bean,需要循环所有的后置处理器,调用它们实现的方法,效率低下。 2. 为了保护单例对象。三级缓存在使用时,beanA和beanB循环依赖,beanA和beanC循环依赖,从三级缓存中获取beanA需要循环所有的后置处理器,但是程序员可以扩展后置处理器,在实现的方法里面可能重新new了一个bean,这时候返回的就不是spring给我们创建的bean了,这样就导致beanB和beanC注入beanA的时候都在后置处理器中new了一个beanA,这样beanB和beanC中注入的beanA并不是同一个对象,这样就破坏了单例,所以二级缓存存在为了防止破坏单例是必须的。
参考文档: