1 概述
Spring利用三级Bean缓存的方式解决Bean循环依赖的问题,三级缓存也就是DefaultSingletonBeanRegistry中的三个Map:
/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name --> bean instance */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
- singletonObjects:一级缓存,存放完整的Bean;
- earlySingletonObjects:二级缓存,存放早期Bean,即还没有设置属性的Bean;
- singletonFactories:三级缓存,存放ObjectFactory对象,即Bean的生产工厂。
一个Bean的创建,经历了 singletonFactories -> earlySingletonObjects -> singletonObjects的三个过程。
处理时机:
- 三级级和二级缓存,在创建bean的时候,即
AbstractAutowireCapableBeanFactory.doCreateBean中设置; - 一级缓存,在获取Bean,即
AbstractBeanFactory.doGetBean中设置。
2 三级缓存&二级缓存
AbstractAutowireCapableBeanFactory.doCreateBean:
// 放入三级缓存
// Bean是单例 && 允许循环依赖 && 当前bean正在创建中
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
if (earlySingletonExposure) {
if (logger.isDebugEnabled()) {
logger.debug("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// addSingletonFactory将一个ObjectFactory放入三级缓存,这个ObjectFactory通过getEarlyBeanReference方法获取对象。
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
//// 省略代码
// 放入二级缓存
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
//// 省略代码
}
2.1 getEarlyBeanReference
/* 遍历beanPostProcessor,如果是SmartInstantiationAwareBeanPostProcessor,则通过getEarlyBeanReference获取Object,否则使用原来实例化的Object。
该方法返回早期对象,用于将来升级到二级缓存: 要么返回原Object,要么返回执行了AbstractAutoProxyCreator.getEarlyBeanReference获取加强后的Object代理对象。
*/
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object 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;
}
2.2 getSingleton
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
// 一级缓存中没有bean
synchronized (this.singletonObjects) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
// 二级缓存中没有早期对象
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
// 从前面的设置的ObjectFactory中,即getEarlyBeanReference方法中,获取早期对象
singletonObject = singletonFactory.getObject();
// 放入二级缓存
this.earlySingletonObjects.put(beanName, singletonObject);
// 清除三级缓存
this.singletonFactories.remove(beanName);
}
}
}
}
return singletonObject;
}
3 一级缓存:
AbstractBeanFactory.doGetBean中:
// 依赖的beanName
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
// getBean调用前面的doCreate将依赖的早期Bean放入二级缓存
getBean(dep);
}
}
// 省略代码....
if (mbd.isSingleton()) {
// 放入一级缓存
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
3.1 getSingleton
getSingleton(String beanName, ObjectFactory<?> singletonFactory) 是AbstractBeanFactory的一个父类DefaultSingletonBeanRegistry中的方法,如过是新的bean,则执行addSingleton(beanName, singletonObject)将对象放入一级缓存中。
protected void addSingleton(String beanName, Object singletonObject) {
synchronized (this.singletonObjects) {
this.singletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
this.earlySingletonObjects.remove(beanName);
this.registeredSingletons.add(beanName);
}
}