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;

}

<bean id="instanceA" class="com.tuling.circulardependencies.InstanceA">

<property name="instanceB" ref="intanceB"></property>

</bean>

<bean id="intanceB" class="com.tuling.circulardependencies.InstanceB">

<property name="instanceA" ref="instanceA"></property>

</bean>

可能存在的问题:

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<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);

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

private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);

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

private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容