什么是循环依赖?
所谓的循环依赖就是A依赖B,B依赖A,或者是A依赖B,B依赖C,C依赖A
代码实例:
getter/setter
public class InstanceA {
private InstanceB instanceB;
}
public class InstanceB {
private InstanceA instanceA;
}
可能存在的问题:
IOC容器在创建Bean的时候,按照顺序,先去实例化instanceA。然后突然发现我的instanceA是依赖我
的instanceB的。
那么IOC容器接着去实例化intanceB,那么在intanceB的时候发现依赖instanceA。若容器不处理的,
那么IOC 将无限的执行
上述流程。直到内存异常程序奔溃.
解决方案:
当然,Spring 是不会让这种情况发生的。在容器发现 beanB 依赖于 beanA 时,容器会获取 beanA
对象的一个早期的引用(early reference),并把这个早期引用注入到 beanB 中,让 beanB 先完成实例
化。beanB 完成实例化,beanA 就可以获取到 beanB 的引用,beanA 随之完成实例化。
看下如下代码调用链
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//检查缓存中是否有初始化好的bean
Object singletonObject = this.singletonObjects.get(beanName);
判断 beanName 对应的 bean 是否正在创建中
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//加锁,防止多线程并发创建
synchronized (this.singletonObjects) {
//从 earlySingletonObjects 中获取提前曝光的 bean
singletonObject = this.earlySingletonObjects.get(beanName);
//也没有
if (singletonObject == null && allowEarlyReference) {
获取相应的 bean 工厂
ObjectFactory> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) { //有
/ // 提前曝光 bean 实例(raw bean),用于解决循环依赖
singletonObject = singletonFactory.getObject();
// 将 singletonObject 放入缓存中,并将 singletonFactory 从缓存中移除
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
用于存放 beanName和 初始化好的bean对象(属性已经初始化好的)
private final Map
存放 bean 工厂对象,用于解决循环依赖
private final Map
用于存放beanName 和一个原始bean 早期bean(属性未初始化)
private final Map