spring為什么要使用三級緩存解決循環(huán)依賴

一 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í)行的后置處理器:


bean后置處理器

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


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容