Spring
的三级缓存是经典面试题,也会看到一些文章讲三级缓存与循环依赖之的关系。那么,三级缓存分别存储的什么呢?他们的作用又分别是什么?
一、一、二级缓存
一级缓存是一个名为 singletonObjects
的 ConcurrentHashMap
,用于存储已经创建完成的 Bean
。其作用也是最明显的,获取 Bean
时最优先从一级缓存中获取。
二级缓存是一个名为 earlySingletonObjects
的 ConcurrentHashMap
,用于存储还未创建完成的 Bean
。在循环依赖时,可以从中预先获取未创建完成的 Bean
,从而解决循环依赖问题。
二、三级缓存
三级缓存是一个名为 singletonFactories
的 ConcurrentHashMap
,用于存储创建指定 Bean
的工厂。其作用是为了在 AOP
代理时解决循环依赖。
更具体可以说,是为了在
AOP
代理时,既解决循环依赖,又最大满足Spring
制定的Bean
生命周期流程。是的,三级缓存一定程度上说,他提前了
Bean
生命周期的流程。
熟悉 Bean
的生命周期可知,Bean
初始化是经过了实例化(createBeanInstance
)、属性注入(populateBean
)、后置处理器与生命周期方法(initializeBean
)三个步骤处理,最终才得到一个创建完成的 Bean
。
在循环依赖时,在属性注入(populateBean
)步骤就要解决依赖问题,而 AOP 代理是在后置处理器与生命周期方法(initializeBean
)步骤中通过后置处理器实现的。如果严格按照 Bean
的这个生命周期执行,依赖注入是无法注入代理之后的对象的。
假设,A 和 B 互相依赖,A 经过 AOP 代理,最终的 Bean
为 Aa
,那么严格按照 Bean
的生命周期最终属性注入的结果如下:
getBean——取得 A Bean,在 doCreateBean 方法中开始创建 Bean 操作。
createBeanInstance——实例化 A Bean。
populateBean——为 A Bean 设置参数,并调用 getBean 方法创建 B Bean。
== createBeanInstance——实例化 B Bean。
== populateBean——为 B Bean 设置参数,并调用 getBean 方法获得未构造完全的 A Bean。
initializeBean——为A Bean 执行后置处理器和生命周期方法,并完成 AOP 代理,获得最终的 Aa Bean。
从上面步骤可以发现,B 中注入的是代理之前的 A 对象,而实际上需要被注入的是代理之后的 Aa 对象。
要解决上述 AOP 代理的问题其实也很简单,只要在 createBeanInstance
步骤中完成 AOP 代理其实一切问题就迎刃而解。但是这并不符合 Bean
的生命周期设定,而且循环依赖的场景很少见,在实例化时也无法判断这个 Bean
是否被循环依赖了,直接将 AOP 代理全部提前执行不合适。
最终,Spring
引入了三级缓存,在实例化对象之后,进行属性注入之前,将实现 AOP 代理的步骤封装为 Bean
工厂放进三级缓存。如果这个对象被循环依赖了,则使用工厂提前进行 AOP 代理,如果没有被循环依赖,则这个工厂就不会被使用。
boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
isSingletonCurrentlyInCreation(beanName));
// 是否需要提前暴露
if (earlySingletonExposure) {
if (logger.isTraceEnabled()) {
logger.trace("Eagerly caching bean '" + beanName +
"' to allow for resolving potential circular references");
}
// 创建bean工厂注入到三级缓存
addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
}
// Initialize the bean instance.
Object exposedObject = bean;
try {
populateBean(beanName, mbd, instanceWrapper);
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
阅读 getEarlyBeanReference
方法逻辑,可以看到其中遍历找到了实现了SmartInstantiationAwareBeanPostProcessor
接口的后置处理器,并执行了其中的 getEarlyBeanReference
方法,提前完成了代理操作,获取到了代理后的最终得对象。文章来源:https://uudwc.com/A/JwOm9
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;
}
在获取对象时,getEarlyBeanReference
便按三级缓存的顺序执行操作,如果在三级缓存中获取到 Bean
工厂,则通过工厂获取对象。文章来源地址https://uudwc.com/A/JwOm9
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
// Quick check for existing instance without full singleton lock
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null && allowEarlyReference) {
synchronized (this.singletonObjects) {
// Consistent creation of early reference within full singleton lock
singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
singletonObject = this.earlySingletonObjects.get(beanName);
if (singletonObject == null) {
ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
if (singletonFactory != null) {
singletonObject = singletonFactory.getObject();
this.earlySingletonObjects.put(beanName, singletonObject);
this.singletonFactories.remove(beanName);
}
}
}
}
}
}
return singletonObject;
}