一 spring為什么要使用多級緩存
首先清楚spring中bean 的加載過程:
1 解析需要spring管理的類為beanDefinition
2 通過反射實例化對象
3 反射設(shè)置屬性
4初始化,調(diào)用initMethod等。(postConstruct也是在這執(zhí)行)
循環(huán)依賴的問題: a依賴b,b依賴a。
在a實例化之后會先將a放入到緩存中,然后給a設(shè)置屬性,去緩存中查到b。此時找不到就開始b的創(chuàng)建。b實例化之后,放入到緩存中,需要給a設(shè)置屬性,此時去緩存中查到a設(shè)置成功。然后初始化。成功后將b放入一級緩存。這個時候a在給自己屬性b設(shè)置值的時候就找到了b,然后設(shè)置b。完成屬性設(shè)置,再初始化,初始化后a放入一級緩存。
二 為什么要使用三級緩存
解決代理對象(如aop)循環(huán)依賴的問題。
例: a依賴b,b依賴a,同時a,b都被aop增強。
首先明確aop的實現(xiàn)是通過 postBeanProcess后置處理器,在初始化之后做代理操作的。
為什么使用三級緩存原因:
1 只使用二級緩存,且二級緩存緩存的是一個不完整的bean
如果只使用二級緩存,且二級緩存緩存的是一個不完整的bean,這個時候a在設(shè)置屬性的過程中去獲取b(這個時候a還沒有被aop的后置處理器增強),創(chuàng)建b的過程中,b依賴a,b去緩存中拿a拿到的是沒有經(jīng)過代理的a。就有問題。
2 使用二級緩存,且二級緩存是一個工廠方法的緩存
如果二級緩存是一個工廠的緩存,在從緩存中獲取的時候獲取到經(jīng)過aop增強的對象??梢钥吹綇墓S緩存中獲取的邏輯。
protected ObjectgetEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
? if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bpinstanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
? ? ? ? ? ? exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
? ? ? ? }
}
}
return exposedObject;
}
a依賴b,b依賴a,c。c又依賴a。a,b,c均aop增強。
加載開始: a實例化,放入工廠緩存,設(shè)置b,b實例化,設(shè)置屬性,拿到a,此時從工廠緩存中拿到代理后的a。由于a沒加載完畢,不會放入一級緩存。這個時候b開始設(shè)置c,c實例化,設(shè)置屬性a,又去工廠緩存中拿對象a。這個時候拿到的a和b從工廠緩存不是一個對象。出現(xiàn)問題。
3 使用二級緩存,二級緩存緩存的是增強后的bean。這個與spring加載流程不符合。spring加載流程是:實例化,設(shè)置屬性,初始化,增強。在有循環(huán)引用的時候,之前的bean并不會增強后放入到二級緩存。
綜上1,2,3 可知二級緩存解決不了有aop的循環(huán)依賴。spring采用了三級緩存。
三 spring的三級緩存
一級緩存? singletonObjects? ? 緩存加載完成的bean。
二級緩存? earlySingletonObjects 緩存從三級緩存中獲取到的bean,此時里面的bean沒有加載完畢。
三級緩存 singletonFactories 。緩存一個objectFactory工廠。
場景:a依賴b,b依賴a和c,c依賴a。并且a,b,c都aop增強。
加載過程:
a實例化,放入三級工廠緩存,設(shè)置屬性b,b實例化放入三級緩存。b設(shè)置屬性a,從三級工廠緩存中獲取代理后的對象a,同時,代理后的a放入二級緩存,然后設(shè)置屬性c,c實例化放入三級緩存,設(shè)置屬性a,此時從二級緩存中獲取到的代理后的a跟b中的a是一個對象,屬性a設(shè)置成功。c初始化,然后執(zhí)行后置處理器。進行aop的增強。增強后將代理的c放入到一級緩存,同時刪除三級緩存中的c。c加載完成,b得到c,b設(shè)置c成功。b初始化,然后執(zhí)行后置處理器,進行aop增強,將增強后的代理對象b放入到一級緩存。刪除三級緩存中的b。此時 a拿到b,設(shè)置屬性b成功,開始初始化,初始化后執(zhí)行后置處理器。在aop的后置處理器中有一個以beanName為key,經(jīng)過aop增強的代理對象為value的map earlyProxyReferences。
這個時候 后置處理器處理對象a的時候,
public ObjectpostProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean !=null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
? ? ? if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
? ? ? }
}
return bean;
}
也就是 發(fā)現(xiàn)這個beanName已經(jīng)被代理后就不在代理。這個時候執(zhí)行后置處理器后,a還是未經(jīng)代理的對象a。此時a再通過getSingleton 重新從緩存中獲取一下a。
Object earlySingletonReference = getSingleton(beanName, false);
false 表示不從三級緩存中取,只從一級,二級緩存中獲取。
這個時候能拿到二級緩存中的a。二級緩存中的a也是經(jīng)過代理后的a。
然后將代理后的a放入到一級緩存中。a加載完畢。
放入一級緩存的過程 :
addSingleton(beanName, singletonObject);
從三級工廠緩存中獲取對象:
protected ObjectgetEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
Object exposedObject = bean;
? if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (BeanPostProcessor bp : getBeanPostProcessors()) {
if (bpinstanceof SmartInstantiationAwareBeanPostProcessor) {
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
? ? ? ? ? ? exposedObject = ibp.getEarlyBeanReference(exposedObject, beanName);
? ? ? ? }
}
}
return exposedObject;
}
其中 AbstractAutoProxyCreator實現(xiàn)該接口。
public ObjectgetEarlyBeanReference(Object bean, String beanName) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
? this.earlyProxyReferences.put(cacheKey, bean);
? return wrapIfNecessary(bean, beanName, cacheKey);
}
wrapIfNecessary()就是真正執(zhí)行代理的。
bean初始化之后執(zhí)行的后置處理器:

其中AbstractAutoProxyCreator 實現(xiàn)了該接口。
