【Spring】三級緩存解決循環依賴問題

1、什麼是循環依賴

    顧名思義“循環依賴”,舉一個簡單的例子A中依賴B,B中依賴A,在實例化對象過程中,填充屬性階段A需要B對象,就去創建B對象,創建B對象的時候,發現B依賴了A,於是又去創建A對象,但此時A對象又沒有創建結束,一級緩存中找不到,於是線程又去創建一個新的A對象,如此一來,就出現了重複創建的現象,最終會導致內存溢出,JVM報錯終止。

2、解決方案

    直接說Spring的解決方案:使用三級緩存。

    設想1:若A、B均爲普通對象(這裏買下代理對象的伏筆),其實來2級緩存就能解決循環依賴,A提前吧自己的早期對象放到二級緩存中即可

    設想2:若涉及到AOP切面代理的場景,就會有問題,你想,當A創建的時候,把早期A放入2級緩存(這時候AOP還沒進行,放入2級緩存的還是原始對象),但是到了B創建的時候,去2級緩存中雖然能找到A的早期對象,但我們都知道,按理說B應該找到A的代理增強對象纔對,所以就引出了3級緩存

    三級緩存解決設想2:A創建的時候,把自己的早期工廠對象(你可以想象這個對象有一個getObject方法,可以拿到代理對象)放入三級緩存,後面B創建的時候直接去三級緩存拿這個早期工廠對象,get到之後(若是正常對象拿到的就是正常對象,若是被代理了這裏拿到的就是代理對象),直接放到二級緩存,B直接拿二級緩存中的A早期代理對象即可,這樣B創建完成,順理成章A也能創建完成。到此循環依賴解決。

3、再說三級緩存原理

     首先我們還是進行實例化A對象,這個時候,我們要將A的ObjectFactory對象放入Map3中。同樣的繼續進行屬性填充,這個時候B還沒創建,於是去創建B。

      那麼去實例化B的過程中,我們也是一樣的,先把B的ObjectFactory放入Map了中。將B對象放入Map2中。

      繼續執行到B的屬性填充,去獲取A對象,而此時Map1中沒有A,因爲A還沒有創建完成,我們則發現Map了中 有A的ObjectFactory對象,那麼我們通過ObjeatFactory對象獲取A的早期對象,然後將這個早期對象放入Map2中,同時刪除Map3中的A,然後我們將A的引用給了B,那麼同樣的B對象這個時候也已經完整了。
      接下來我們再把B放入Map中接下來從Map3中刪除B。這時候B已經創建完成,A繼續執行b的屬性填充可以拿到B對象,這樣A也完成,最後我們把A對象也放入了Map,刪除掉Map2中的A。於是我們的儲環依賴就此解決。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章