spring源码深度解析— IOC 之 循环依赖处理

  • 时间:
  • 浏览:66
  • 来源:蓝点资源网_提供可可资源网技术_ACE资源网资讯

addSingletonFactory() 代码如下:

Spring 只外理 scope 为 singleton 的循环依赖,对于scope 为 prototype 的 bean Spring 无法外理,直接抛出 BeanCurrentlyInCreationException 异常。

加进去去至一级缓存,一起从二级、三级缓存中删除。你這個 辦法 在亲戚亲戚大家儿创建 bean 的链路中有 哪个地方引用呢?其随便说说前面博客 LZ 前一天提到过了,在 doGetBean() 外理不同 scope 时,前一天是 singleton,则调用 getSingleton(),如下:

曾经就从三级缓存升级到二级缓存了。

也某些某些我亲戚亲戚大家儿上一篇文章中讲的最后一部分,提前将创建好但还未进行属性赋值的的Bean放上去缓存中。

到这里,关于 Spring 外理 bean 循环依赖就前一天分析完毕了。最已经 描述下就里边那个循环依赖 Spring 外理的过程:首先 A 完成初始化第一步并将某些人提前曝光出来(通过 ObjectFactory 将某些人提前曝光),在初始化的前一天,发现某些人依赖对象 B,此时就会去尝试 get(B),你這個 前一天发现 B 还没法被创建出来,因此 B 就走创建流程,在 B 初始化的前一天,同样发现某些人依赖 C,C 也没法被创建出来,你這個 前一天 C 又开始英文了了初始化程序,因此在初始化的过程中发现某些人依赖 A,于是尝试 get(A),你這個 前一天前一天 A 前一天加进去去至缓存中(一般与非 加进去去至三级缓存 singletonFactories ),通过 ObjectFactory 提前曝光,某些某些回会 通过 ObjectFactory.getObject() 拿到 A 对象,C 拿到 A 对象后顺利完成初始化,因此将某些人加进去去到一级缓存中,回到 B ,B 也回会 拿到 C 对象,完成初始化,A 回会 顺利拿到 B 完成初始化。到这里整个链路就前一天完成了初始化过程了。

你這個 辦法 主某些某些我从曾经缓存中获取,分别是:singletonObjects、earlySingletonObjects、singletonFactories,三者定义如下:

getSingleton() 整个过程如下:首先从一级缓存 singletonObjects 获取,前一天没法且当前指定的 beanName 正在创建,就再从二级缓存中 earlySingletonObjects 获取,前一天还是没法获取到且运行 singletonFactories 通过 getObject() 获取,则从三级缓存 singletonFactories 获取,前一天获取到则,通过其 getObject() 获取对象,并将其加入到二级缓存 earlySingletonObjects 中 从三级缓存 singletonFactories 删除,如下:

注意,这里与非 函数的循环调用,是对象的相互依赖关系。循环调用随便说说某些某些我曾经死循环,除非有终结条件。

Spring中循环依赖场景有:

(1)构造器的循环依赖

(2)field属性的循环依赖。 

亲戚亲戚大家某些某些我 Spring 外理 singleton bean 的关键因素所在,我称亲戚亲戚大家为三级缓存,第一级为 singletonObjects,第二级为 earlySingletonObjects,第三级为 singletonFactories。这里亲戚亲戚大家儿回会 通过 getSingleton() 想看 亲戚亲戚大家是怎么配合的,这分析该辦法 前一天,提下其中的 isSingletonCurrentlyInCreation() 和 allowEarlyReference

介绍到这里亲戚亲戚大家儿发现三级缓存 singletonFactories 和 二级缓存 earlySingletonObjects 中的值与非 出处了,那一级缓发生哪里设置的呢?在类 DefaultSingletonBeanRegistry 中回会 发现你這個  addSingleton() 辦法 ,源码如下:

这三级缓存分别指:

(1)singletonFactories : 单例对象工厂的cache

(2)earlySingletonObjects :提前暴光的单例对象的Cache

(3)singletonObjects:单例对象的cache

至此,Spring 关于 singleton bean 循环依赖前一天分析完毕了。某些某些亲戚亲戚大家儿基本上回会 选泽 Spring 外理循环依赖的方案了:Spring 在创建 bean 的前一天暂且是等它完整性完成,某些某些我在创建过程中将创建中的 bean 的 ObjectFactory 提前曝光(即加入到 singletonFactories 缓存中),曾经一旦下曾经 bean 创建的前一天时需依赖 bean ,则直接使用 ObjectFactory 的 getObject() 获取了,也某些某些我 getSingleton()中的代码片段了。

循环依赖随便说说某些某些我循环引用,也某些某些我曾经或则曾经以上的bean互相持有对方,最终形成闭环。比如A依赖于B,B依赖于C,C又依赖于A。如下图所示:

在 doGetBean() 中,首先会根据 beanName 从单例 bean 缓存中获取,前一天不为空则直接返回。

对于构造器的循环依赖,Spring 是无法外理的,不回会 抛出 BeanCurrentlyInCreationException 异常表示循环依赖,某些某些下面亲戚亲戚大家儿分析的与非 基于 field 属性的循环依赖。

亲戚亲戚大家儿先从加载 bean 最初始的辦法  doGetBean() 开始英文了了。

检测循环依赖相对比较容易,Bean在创建的前一天回会 给该Bean打标,前一天递归调用回来发现正在创建中话语,即说明了循环依赖了。

从这段代码亲戚亲戚大家儿回会 看出 singletonFactories 你這個 三级缓存才是外理 Spring Bean 循环依赖的诀窍所在。一起这段代码发生在 createBeanInstance() 辦法 前一天,也某些某些我说你這個 bean 随便说说前一天被创建出来了,因此它还与非 很完美(没法进行属性填充和初始化),因此对于某些依赖它的对象而言前一天足够了(回会 根据对象引用定位到堆中对象),回会 被认出来了,某些某些 Spring 在你這個 前一天选泽将该对象提前曝光出来让亲戚亲戚大家儿认识认识。

里边是从缓存中获取,因此缓存中的数据从哪里加进去去进来的呢?时不时往下跟会发现在 doCreateBean() ( AbstractAutowireCapableBeanFactory ) 中,有没法一段代码:

前一天 earlySingletonExposure == true 话语,则调用 addSingletonFactory() 将亲戚亲戚大家加进去去到缓存中,因此曾经 bean 要具备如下条件才会加进去去至缓存中: