问题
public class A {
private B b;
}
public class B {
private A a;
}
/**********************/
<bean id="beanA" class="xyz.coolblog.BeanA">
<property name="beanB" ref="beanB"/>
</bean>
<bean id="beanB" class="xyz.coolblog.BeanB">
<property name="beanA" ref="beanA"/>
</bean>
Bean的实例化分三步
createBeanInstance实例化 -> populateBean 填充属性 -> initializeBean初始化
如何解决
为了解决单例的循环依赖问题,使用了三级缓存,递归调用发现Bean还在创建中即为循环依赖
/** 一级缓存:用于存放完全初始化好的 bean **/
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(256);
/** 二级缓存:存放原始的 bean 对象(尚未填充属性),用于解决循环依赖 */
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
/** 三级级缓存:存放 bean 工厂对象,用于解决循环依赖 */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>(16);
/**
bean 的获取过程:先从一级获取,失败再从二级、三级里面获取
创建中状态:是指对象已经 new 出来了但是所有的属性均为 null 等待被 init
*/
比如:1) A创建过程中需要B,于是A先放入到三级缓存中,去实例化B
2) B实例化时需要A,于是B先查一级缓存,没有,在查二级缓存,还是没有,再查三级缓存,找到啦!
3)然后三级缓存里面这个A放到二级缓存中,并删除三级缓存里面的A
4) B初始化完毕,放入到一级缓存中(此时B中A还再创建中状态)
5)然后接着创建A,此时B已经创建结束,直接从一级缓存中拿到B,然后完成创建,并将自己放到一级缓
存里面
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
一句话:先让最底层对象完成初始化,通过三级缓存与二级缓存提前曝光创建中的 Bean,让其他 Bean 率先完成初始化。
网友评论