ToB企服应用市场:ToB评测及商务社交产业平台

标题: Spring源码解析——IOC之循环依赖处理 [打印本页]

作者: 忿忿的泥巴坨    时间: 2023-10-19 11:44
标题: Spring源码解析——IOC之循环依赖处理
什么是循环依赖

循环依赖其实就是循环引用,也就是两个或则两个以上的bean互相持有对方,最终形成闭环。比如A依赖于B,B依赖于C,C又依赖于A。如下图所示:

注意,这里不是函数的循环调用,是对象的相互依赖关系。循环调用其实就是一个死循环,除非有终结条件。
最全面的Java面试网站
Spring中循环依赖场景有:
(1)构造器的循环依赖
(2)field属性的循环依赖。
对于构造器的循环依赖,Spring 是无法解决的,只能抛出 BeanCurrentlyInCreationException 异常表示循环依赖,所以下面我们分析的都是基于 field 属性的循环依赖。
Spring 只解决 scope 为 singleton 的循环依赖,对于scope 为 prototype 的 bean Spring 无法解决,直接抛出 BeanCurrentlyInCreationException 异常。
如何检测循环依赖

检测循环依赖相对比较容易,Bean在创建的时候可以给该Bean打标,如果递归调用回来发现正在创建中的话,即说明了循环依赖了。
解决循环依赖

我们先从加载 bean 最初始的方法 doGetBean() 开始。
在 doGetBean() 中,首先会根据 beanName 从单例 bean 缓存中获取,如果不为空则直接返回。
  1. protected Object getSingleton(String beanName, boolean allowEarlyReference) {
  2.     Object singletonObject = this.singletonObjects.get(beanName);
  3.     if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
  4.         synchronized (this.singletonObjects) {
  5.             singletonObject = this.earlySingletonObjects.get(beanName);
  6.             if (singletonObject == null && allowEarlyReference) {
  7.                 ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
  8.                 if (singletonFactory != null) {
  9.                     singletonObject = singletonFactory.getObject();
  10.                     this.earlySingletonObjects.put(beanName, singletonObject);
  11.                     this.singletonFactories.remove(beanName);
  12.                 }
  13.             }
  14.         }
  15.     }
  16.     return singletonObject;
  17. }
复制代码
这个方法主要是从三个缓存中获取,分别是:singletonObjects、earlySingletonObjects、singletonFactories,三者定义如下:
[code]private final Map singletonObjects = new ConcurrentHashMap(256);private final Map




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4