7.1何为循环依赖?
- 循环依赖其实就是循环引用,也就是两个或两个以上的bean互相持有对方,最终形成闭环。比如,A依赖于B,而B又依赖于A。
- Spring处理:循环依赖在Spring中是允许存在的,因为Spring框架依据三级缓存机制已经解决了大部分的循环依赖问题。
7.2三级缓存解析
- 一级缓存(singletonObjects):单例池,存放已历经完整生命周期(实例化、注入、初始化)的bean对象。
- 二级缓存(earlySingletonObjects):缓存实例化完成的bean对象。
- 三级缓存(singletonFactories):存放ObiectFactory对象,它们能用来创建对应bean的实例。
7.3三级缓存解决循环依赖
首先开始实例化beanA,同时在三级缓存中创建一个与A关联的ObiectFactory对象并存入
singletonFactories
7.3.2创建B的需求
A在初始化过程中需要B对象,于是触发B的创建逻辑
7.3.3实例化B
B被实例化完成后,同样会在三级缓存singletonFactories中为其创建一个ObjectFactory。
7.3.4注入A到B
- 当B需要注入A时,会通过三级缓存中对应的ObiectFactory生成A的对象,并将其存入二级缓存earlySingletonObjects。
- 这里生成的A对象可能是原始对象,也可能是代理对象,关键在于ObjectFactory都能胜任生产任务。
7.3.5B创建完成
- B成功从二级缓存
earlySingletonObiects获取到A对象并完成注入,此时B创建完毕,被放入一级缓存singletonObiects。
7.3.6回溯至A
- 回到A的初始化过程,由于B现在已存在于一级缓存中,A可以直接注入B,完成自身的初始化,
7.3.7清理二级缓存
- 最后,二级缓存中用于临时存储的A对象会被清除,确保缓存状态的整洁。
7.4为什么不能用二级缓存解决循环依赖?
-
其实二级缓存同样也能很好解决循环引用问题。
-
使用三级而非二级缓存并非出于IOC的考虑,而是出于AOP的考虑,即若使用二级缓存,在AOP情形下 , 注入到其他bean的,不是最终的代理对象,而是原始对象。
-
循环依赖下,有没有代理情况下的区别就在:
singletonObject = singletonFactory.getObject();
在循环依赖发生的情况下 B 中的 A 赋值时:
- 无代理:getObject 直接返回原来的 Bean
- 有代理:getObject 返回的是代理对象
然后都放到二级缓存。