前言
关于spring解决循环依赖的问题,在之前第二篇讲Bean的实例化与初始化的时候,有3个地方提到过循环依赖的问题,可以来看看这3个地方是怎么实现的
获取提前暴露的Bean
在AbstractBeanFactory#doGetBean方法中的第一步,就是尝试从缓存中拿到bean,
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
//.....创建新的bean
}
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
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;
}
这里的逻辑是这样的:
1.先尝试从singletonObjects中获取bean对象,如果已经存在该单例bean,则直接返回
2.再尝试从earlySingletonObjects中找bean对象,如果可以找到,变直接返回
3.如果earlySingletonObjects中还没有,则从singletonFactories中获取,如果能找到ObjectFactory,则调用ObjectFactory的getObject的方法,生成对象,放入earlySingletonObjects,并删除对应的BeanFactory
可以看到,这里是有3个缓存,singletonObjects比较清楚,就是用来存放单例的,earlySingletonObjects和singletonFactories又是在什么时候处理的呢?
将bean提前暴露
一层层深入,到了AbstractAutowireCapableBeanFactory#doCreateBean方法中
// bean的实例化
BeanWrapper instanceWrapper = null;
instanceWrapper = createBeanInstance(beanName, mbd, args);
//....
//在进入该方法前,会先将beanName放入singletonsCurrentlyInCreation中
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
addSingletonFactory(beanName, (beanName, mbd, bean) -> {
Object exposedObject = bean;
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
}
}
}
return exposedObject;
});
}
protected void addSingletonFactory(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
if (!this.singletonObjects.containsKey(beanName)) {
this.singletonFactories.put(beanName, singletonFactory);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}
}
至此,也就可以说通了,在实例化完成之后,初始化之前,如果可以判定某个bean正处在创建中,那边就会生成一个ObjectFactory,放入singletonFactories中,下次就会直接根据ObjectFactory这个三级缓存直接返回对象。
当然,这里我们还看到了SmartInstantiationAwareBeanPostProcessor这种BeanPostProcessor,这种BeanPostProcessor的具体的用处还真是不太清楚,但从代码中可以推断出来,如果要对提前暴露的Bean做个处理(还未初始化),则可以通过这种处理器
总结
举个简单的例子:
A和B互相依赖
- getBean(A)
- addSingletonFactory(A)
- getBean(B)
- addSingletonFactory(B)
- getBean(A)
- singletonFactories.get(A).getObject(),返回已经提前实例好但为初始化的Bean实例