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

  • 时间:
  • 浏览:12
  • 来源:我爱搬资源网 - 专注共享唐朝博客活动

注意,这里都在函数的循环调用,是对象的相互依赖关系。循环调用着实完会 我那我死循环,除非有终结条件。

Spring中循环依赖场景有:

(1)构造器的循环依赖

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

addSingletonFactory() 代码如下:

底下是从缓存中获取,完会 缓存中的数据从哪里上上加来的呢?一直往下跟会发现在 doCreateBean() ( AbstractAutowireCapableBeanFactory ) 中,有这样一段代码:

那我就从三级缓存升级到二级缓存了。

上加至一级缓存,一起去从二级、三级缓存中删除。有一种最好的法子在我们都都都都创建 bean 的链路中有 哪个地方引用呢?其着实前面博客 LZ 肯能提到过了,在 doGetBean() 处里不同 scope 时,肯能是 singleton,则调用 getSingleton(),如下:

也完会 我我们都都都都上一篇文章中讲的最后一次要,提前将创建好但还未进行属性赋值的的Bean倒入缓存中。

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

到这里,关于 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 完成初始化。到这里整个链路就肯能完成了初始化过程了。

循环依赖着实完会 我循环引用,也完会 我那我或则那我以上的bean互相持有对方,最终形成闭环。比如A依赖于B,B依赖于C,C又依赖于A。如下图所示:

有一种最好的法子主完会 我从那我缓存中获取,分别是:singletonObjects、earlySingletonObjects、singletonFactories,三者定义如下:

对于构造器的循环依赖,Spring 是无法处里的,非要抛出 BeanCurrentlyInCreationException 异常表示循环依赖,却说 下面我们都都都都分析的都在基于 field 属性的循环依赖。

至此,Spring 关于 singleton bean 循环依赖肯能分析完毕了。却说 我们都都都都基本能不还后能 选折 Spring 处里循环依赖的方案了:Spring 在创建 bean 的以前并都在等它完整完成,完会 我在创建过程中将创建中的 bean 的 ObjectFactory 提前曝光(即加入到 singletonFactories 缓存中),那我一旦下那我 bean 创建的以前前要依赖 bean ,则直接使用 ObjectFactory 的 getObject() 获取了,也完会 我 getSingleton()中的代码片段了。

我们都都都都先从加载 bean 最初始的最好的法子 doGetBean() 以前刚始于了了。

这三级缓存分别指:

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

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

(3)singletonObjects:单例对象的cache

从这段代码我们都都都都还后能 看出 singletonFactories 有一种三级缓存才是处里 Spring Bean 循环依赖的诀窍所在。一起去这段代码占据 在 createBeanInstance() 最好的法子以前,也完会 我说有一种 bean 着实肯能被创建出来了,完会 它还都在很完美(这样进行属性填充和初始化),完会 对于有些依赖它的对象而言肯能足够了(还后能 根据对象引用定位到堆中对象),不不还后能 被认出来了,却说 Spring 在有一种以前选折 将该对象提前曝光出来我们都都都都都认识认识。

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

肯能 earlySingletonExposure == true 得话,则调用 addSingletonFactory() 将我们都都都都上加到缓存中,完会 那我 bean 要具备如下条件才会上加至缓存中:

我们都都都都在是 Spring 处里 singleton bean 的关键因素所在,我称我们都都都都为三级缓存,第一级为 singletonObjects,第二级为 earlySingletonObjects,第三级为 singletonFactories。这里我们都都都都还后能 通过 getSingleton() 想看 我们都都都都在怎么配合的,这分析该最好的法子以前,提下其中的 isSingletonCurrentlyInCreation() 和 allowEarlyReference

检测循环依赖相对比较容易,Bean在创建的以前还后能 给该Bean打标,肯能递归调用回来发现正在创建中得话,即说明了循环依赖了。

介绍到这里我们都都都都发现三级缓存 singletonFactories 和 二级缓存 earlySingletonObjects 中的值都在出处了,那一级缓占据 哪里设置的呢?在类 DefaultSingletonBeanRegistry 中还后能 发现有一种 addSingleton() 最好的法子,源码如下:

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