【Spring】Spring中是如何解决循环依赖的问题呢?

在Spring中,解决循环依赖,只有属性注入的方式而且还是单例的,才可以解决循环依赖的问题,构造器和属性注入多例的都是不能够解决循环依赖的

1、构造器参数循环依赖

Spring容器会将每一个正在创建的 Bean 标识符放在一个“当前创建Bean池”中,Bean标识符在创建过程中将一直保持在这个池中,因此如果在创建Bean过程中发现自己已经在“当前创建Bean池”里时将抛出BeanCurrentlyInCreationException异常表示循环依赖;而对于创建完毕的Bean将从“当前创建Bean池”中清除掉。

2、属性注入方式-多例

“prototype”作用域Bean,Spring容器无法完成依赖注入,因为“prototype”作用域的Bean,Spring容器不进行缓存,因此无法提前暴露一个创建中的Bean

3、属性注入方式-单例

使用了三级缓存,提前曝光
singletonFactories : 进入实例化阶段的单例对象工厂的cache (三级缓存)
earlySingletonObjects :完成实例化但是尚未初始化的,提前暴光的单例对象的Cache (二级缓存)
singletonObjects:完成初始化的单例对象的cache(一级缓存)
提前曝光,当前Bean A实例化完,还没有初始化完就先把当前Bean曝光出去,在B初始化需要依赖A的时候,就先拿到提前曝光的A,这样就可以继续将B初始化完成,然后返回A继续进行初始化。

利用三级缓存解决循环依赖的详细过程

假如A和B相互依赖
(1)初始化Bean A,此时三个缓存中都是空,singletonObjects: [null], earlySingletonObjects: [], singletonFactories: [null]
(2)实例化Bean A,将A放入到singletonFactories中,此时singletonObjects: [null], earlySingletonObjects: [], singletonFactories: [A]。
(3)实例化A之后,需要注入依赖的属性,发现A依赖B,开始初始化Bean B,此时singletonObjects: [null], earlySingletonObjects: [], singletonFactories: [A]
(4)实例化Bean B,将B放入到singletonFactories中,此时singletonObjects: [null], earlySingletonObjects: [], singletonFactories: [A, B]
(5)实例化B之后,需要注入依赖的属性,发现B依赖A,此时需要初始化A,这时候初始化A会去singletonFactories查找一下,发现存在A,直接获取A并放入earlySingletonObjects中,然后从singletonFactories删除,此时singletonObjects: [null], earlySingletonObjects: [A], singletonFactories: [B]
(6)此时B就拿到了上一步在singletonFactories中存在的A,B依赖注入完成,此时singletonObjects: [null], earlySingletonObjects: [A], singletonFactories: [B]
(7)B依赖注入完成后继续初始化完成,会将B从earlySingletonObjects和singletonFactories中删除,添加进singletonObjects中,此时singletonObjects: [B], earlySingletonObjects: [A], singletonFactories: [null]
(8)接下来继续进行A的依赖注入,此时B已经初始化完成了,直接将B注入给A,然后A继续下面的初始化直到A完成,此时singletonObjects: [B], earlySingletonObjects: [A], singletonFactories: [null]
(9)A初始化完成之后,会从earlySingletonObjects和singletonFactories中删除,添加进singletonObjects中,此时singletonObjects: [A, B], earlySingletonObjects: [null], singletonFactories: [null]
(10)这样就完成了循环依赖的解决。

©️2020 CSDN 皮肤主题: Age of Ai 设计师:meimeiellie 返回首页