参考资料:
spring为什么使用三级缓存而不是两级? - 知乎 (zhihu.com)
【超级干货】为什么spring一定要弄个三级缓存? - 知乎 (zhihu.com)
关键类:
- AbstractBeanFactory:getBean、doGetBean
- AbstractAutowireCapableBeanFactory:createBean、doCreateBean、getEarlyBeanReference
- DefaultSingletonBeanRegistry:getSingleton
- AbstractAutoProxyCreator:getEarlyBeanReference、postProcessAfterInitialization
//AbstractBeanFactory
//两个不同的getSingleton就是三级缓存的关键之处
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
//尝试从缓存里拿这个bean,这里的getSingleton和下面的不同
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
}
//缓存里拿不到,创建一个bean
else {
//这个getSingleton和上面的不同,它不是从缓存里拿,它要创建一个bean
//最终调用工厂的getObject,而getObject实质上就是createBean
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return createBean(beanName, mbd, args);
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
}
//……
return (T) bean;
}
//DefaultSingletonBeanRegistry
//用工厂创建bean的getSingleton
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
// 将当前的bean标记为正在创建中
beforeSingletonCreation(beanName);
//调用上面传过来的工厂的getObject方法创建对象
//联系上文,实际上调用了createBean->doCreateBean
singletonObject = singletonFactory.getObject();
if (recordSuppressedExceptions) {
this.suppressedExceptions = null;
}
// 取消当前bean的创建中标记
afterSingletonCreation(beanName);
//将创建出来的bean注入一级缓存,并去除二级三级缓存的相关信息
addSingleton(beanName, singletonObject);
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
//从缓存里拿bean的getSingleton,处理AOP
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) {
//从三级缓存里拿出工厂,然后调用它的getObject
//联系下文,这里其实调用了getEarlyBeanReference
singletonObject = singletonFactory.getObject();
//将工厂从三级缓存里去除,将工厂生产出来的bean注入到二级缓存里
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
//AbstractAutowireCapableBeanFactory
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
throws BeanCreationException {
//构造一个原生的bean
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
}
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
final Object bean = instanceWrapper.getWrappedInstance();
Class<?> beanType = instanceWrapper.getWrappedClass();
mbd.resolvedTargetType = beanType;
//判定当前的bean是否正在创建中
boolean earlySingletonExposure =; //……&&isSingletonCurrentlyInCreation(beanName)
//将一个匿名的工厂放进三级缓存,这个工厂调用了getEarlyBeanReference
//这里是三级缓存的关键,检查getEarlyBeanReference
if (earlySingletonExposure) {
addSingletonFactory(beanName, new ObjectFactory<Object>() {
@Override
public Object getObject() throws BeansException {
return getEarlyBeanReference(beanName, mbd, bean);
}
});
}
//初始化这个bean,注入对象字段的值,这里产生循环依赖
//如果没有循环依赖且有代理,这里返回代理,否则返回原对象
//initializeBean方法会调用bean所有的后置处理器,而AOP的代理就是在后置处理器中完成的
Object exposedObject = bean;
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
//从一级和二级缓存中获取该bean,如果有就替换掉原来的bean
//这是为了解决循环依赖时,AOP后置处理器提前执行导致initialize返回原bean的问题
if (earlySingletonExposure) {
Object earlySingletonReference = getSingleton(beanName, false);
if (earlySingletonReference != null) {
if (exposedObject == bean) {
exposedObject = earlySingletonReference;
}
//……
}
}
registerDisposableBeanIfNecessary(beanName, bean, mbd);
return exposedObject;
}
//AbstractAutowireCapableBeanFactory
//遍历所有的后置处理器,挑出AOP的后置处理器提前执行
protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
if (bean != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
//如果对象被AOP代理了,他就会进入这个分支,返回代理对象(前提是这是第一次进行代理)
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
if (exposedObject == null) {
return null;
}
}
}
}
return exposedObject;
}
//AOP的后置处理器:AbstractAutoProxyCreator
//后置代理
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
//从这里就可以看出如果提前执行了,后置处理器不会再执行
//只有第一个bean会返回代理bean,其他的都返回自身
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
//提前代理,发现它是可以对同一个对象执行多次的,所以单例生产完代理一定要清除三级缓存
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
//在这里加上了,后置处理就不会执行了
this.earlyProxyReferences.add(cacheKey);
}
return wrapIfNecessary(bean, beanName, cacheKey);
}
总结:
-
三个缓存
- 一级缓存:保存已经完全可用的bean
- 二级缓存:保存未初始化的原bean或者代理bean(AOP)
- 三级缓存:保存FactoryBean,这个工厂并没有生产原bean的能力,调用它就是找到AOP后置处理器,然后根据原bean生成一个代理
-
无循环依赖的流程,从doGetBean开始
- 通过
getSingleton
从缓存1~3中拿bean,因为没有循环依赖,所以肯定为空 - 通过重载过的
getSingleton
创建一个原bean,实质上调用doCreateBean doCreateBean
通过反射创建一个原bean,将原bean封装在一个FactoryBean中,注入三级缓存- 注入属性、初始化,最后执行后置处理器,通过
initializeBean
调用applyBeanPostProcessorsBeforeInitialization
执行后置处理器 - AOP的后置处理器执行,调用
AbstractAutoProxyCreator
生成代理对象,由于是第一次调用AbstractAutoProxyCreator#getEarlyBeanReference
,所以会生成代理,而非直接返回原对象 - 检测一级和二级缓存,准备替换最终对象,发现是空的,所以不替换
- 清空二级和三级缓存
- 返回代理bean
- 通过
-
循环依赖的流程,从doGetBean开始
- 通过
getSingleton
从缓存1~3中拿bean,因为刚开始,所以肯定为空 - 通过重载过的
getSingleton
创建一个原bean,实质上调用doCreateBean doCreateBean
通过反射创建一个原bean,将原bean封装在一个FactoryBean中,注入三级缓存- 注入属性,由于循环依赖,所以创建bean2的时候又会获取bean,进入doGetBean
- 通过
getSingleton
从缓存1~3中拿bean,由于缓存3有一个FactoryBean,所以通过FactoryBean获取bean,FactoryBean调用getObject
,getObject调用getEarlyBeanReference
getEarlyBeanReference
找到AOP的后置处理器提前执行,生成代理,其原理和initialize完成AOP一样。然后注入二级缓存,删除三级缓存。- 回到bean的初始化过程,现在属性注入完成,要执行后置处理器了。
- AOP的后置处理器执行,调用
AbstractAutoProxyCreator
生成代理对象,由于是第二次调用AbstractAutoProxyCreator#getEarlyBeanReference
,所以不会生成代理,返回原对象 - 检测一级和二级缓存,准备替换最终对象,发现二级缓存有东西,替换掉后置处理器返回的原bean
- 清空二级和三级缓存
- 返回代理bean
- 通过
-
可以看到关键点就是两个
getSingleton
,两个FactoryBean
以及后置处理器-
两个getSingleton:
- 第一个getSingleton尝试从1~3级缓存中获取bean,第三级缓存获取到factorybean时会调用它的getObject方法来得到bean
- 第二个getSingleton单纯就是通过传入的factoryBean来获取bean
-
两个FactoryBean:
- 第一种FactoryBean是在反射创建完一个空对象后注入到三级缓存中的。它的getObject调用了
getEarlyBeanReference
,本质上就是让后置处理器立刻执行,所以此时如果有AOP,代理对象就会在此处生成(前提是调用了这个FactoryBean,也就是有循环依赖) - 第二种FactoryBean是在第二次调用getSingleton时注入到该方法中的,它调用了
createBean
,本质上就是反射创建空对象
- 第一种FactoryBean是在反射创建完一个空对象后注入到三级缓存中的。它的getObject调用了
-
后置处理器:在一般的流程中,对象初始化完后就会执行所有后置处理器,而AOP也通过后置处理器完成。但是如果有循环依赖,就会在第二次getBean的时候提前执行一次AOP的后置处理器
普通情况: getBean1->doCreate->populate->initialize->执行所有后置处理器 循环依赖: getBean1->doCreate->populate->某个bean又依赖了bean1->getBean1 ->从三级缓存里获取factorybean->factorybean启动了bean1的AOP后置处理器 ->populate结束,返回bean1的流程->initialize bean1->执行bean1的所有后置处理器
-
所以三级缓存本质上就是为了优雅地提前AOP的后置处理器执行设计的。
- 如果没有AOP,两层缓存足矣,生产一个空bean就注入二级缓存,循环依赖就从二级缓存里拿。
- 但如果有AOP,这样就会导致另外的bean拿到的不是代理对象,所以生产bean时就要直接生成一个代理对象,但是AOP原来就是设计在后置处理器里完成的,这样就破坏了原先的设计,而且我们还要分清楚代理对象和原对象,因为属性是要注入到原对象里面的。
- 所以需要设计一种结构
- 第一次获取时得到原对象,让属性注入给原对象
- 而第二次获取时得到代理对象,让依赖该对象的得到代理对象
- 同时AOP要在后置处理器里完成
- 而且最后要返回代理对象,且这个代理对象是其他循环依赖对象中的那个。
- 三级缓存+二级缓存检测就是按照这种思路来的,设原对象为A,代理对象为A1,循环依赖对象为B
- 第一次获取时,三级缓存里没有东西,所以会创建一个A:getSingleton、doCreateBean,同时将一个FactoryBean放到三级缓存里,准备让B调用
- 对A进行属性注入,同时触发循环依赖
- B尝试获取A时发现三级缓存里有东西,通过FactoryBean获取对象,而FactoryBean提前启动了AOP后置处理器(getEarlyBeanReference),返回A1,同时将A1放到二级缓存里。
- 删除三级缓存,如果其他对象也循环依赖A,就不会重复生成不同的代理对象了。(getEarlyBeanReference可以重复生成代理)
- B完成初始化,返回完全可用的对象,A将其拿到并注入自身,此时B保有A1,而A保有B,A1没有B,符合要求。
- A的属性注入完成,启动后置处理器链条,由于代理已经执行过了,所以还是返回A
- 最后检查二级缓存,发现有一个A1,用A1替换A,返回A1
- 可以看到,AOP就是在后置处理器里完成的,没有破坏原有的设计,只不过三级缓存里的FactoryBean会将其提前执行罢了
-