Spring循环依赖
什么是循环依赖
所谓的循环依赖是指,A 依赖 B,B 又依赖 A,它们之间形成了循环依赖。或者是 A 依赖 B,B 依赖 C,C 又依赖 A。
public class BeanB {
private BeanA beanA;
}
public class BeanA {
private BeanB beanB;
}
配置文件如下
<bean id="beanA" class="xxx.xxx.BeanA">
<property name="beanB" ref="beanB"/>
</bean>
<bean id="beanB" class="xxx.xxx.BeanB">
<property name="beanA" ref="beanA"/>
</bean>
IOC容器在读到上面的配置时,会按照顺序,先去实例化 beanA。然后发现 beanA 依赖于 beanB,接在又去实例化 beanB。实例化 beanB 时,发现 beanB 又依赖于 beanA。
如果容器不处理循环依赖的话,容器会无限执行上面的流程,直到内存溢出,程序崩溃。
当然,Sprin 是不会让这种情况发生的。在容器再次发现 beanB 依赖于 beanA 时,容器会获取 beanA 对象的一个早期的引用(early reference),并把这个早期引用注入到 beanB 中,让 beanB 先完成实例化。beanB 完成实例化,beanA 就可以获取到 beanB 的引用,beanA 随之完成实例化。
所谓的”早期引用“是指向原始对象的引用。所谓的原始对象是指刚创建好的对象,但还未填充属性。
一些缓存的介绍
/** Cache of singleton objects: bean name --> bean instance */
/** 用于存放完全初始化好的 bean,从该缓存中取出的 bean 可以直接使用 */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
/** Cache of singleton factories: bean name --> ObjectFactory */
/** 存放 bean 工厂对象,用于解决循环依赖 */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
/** Cache of early singleton objects: bean name --> bean instance */
/** 存放原始的 bean 对象(尚未填充属性),用于解决循环依赖 */
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);