Spring 是如何解决循环依赖的

什么是循环依赖?

所谓的循环依赖就是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 singletonObjects = new ConcurrentHashMap(256);

存放 bean 工厂对象,用于解决循环依赖

private final Map> singletonFactories = new HashMap>(16);

用于存放beanName 和一个原始bean 早期bean(属性未初始化)

private final Map earlySingletonObjects = new HashMap(16);

你可能感兴趣的:(Spring 是如何解决循环依赖的)