<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Spring如何解決循環(huán)依賴

          共 2225字,需瀏覽 5分鐘

           ·

          2021-03-14 18:18

          點擊上方藍色字體,選擇“標(biāo)星公眾號”

          優(yōu)質(zhì)文章,第一時間送達

            作者 |  MXC肖某某

          來源 |  urlify.cn/ZriUjy

          一、什么是循環(huán)依賴

            多個bean之間相互依賴,形成了一個閉環(huán)。比如:A依賴于B、B依賴于c、c依賴于A

            通常來說,如果問spring容器內(nèi)部如何解決循環(huán)依賴, 一定是指默認的單例Bean中,屬性互相引用的場景。也就是說,Spring的循環(huán)依賴,是Spring容器注入時候出現(xiàn)的問題。

              


          二、Spring如何解決循環(huán)依賴


          1,Spring中單例Bean的三級緩存

            

          • 第一級緩存〈也叫單例池)singletonObjects:存放已經(jīng)經(jīng)歷了完整生命周期的Bean對象

          • 第二級緩存: earlySingletonObjects,存放早期暴露出來的Bean對象,Bean的生命周期未結(jié)束(屬性還未填充完整)

          • 第三級緩存: Map<String, ObiectFactory<?>> singletonFactories,存放可以生成Bean的工廠


          2,Spring中Bean的生命周期

                

               


          3,Bean初始化主要方法

            

          • getSingleton:希望從容器里面獲得單例的bean,沒有的話

          • doCreateBean: 沒有就創(chuàng)建bean

          • populateBean: 創(chuàng)建完了以后,要填充屬性

          • addSingleton: 填充完了以后,再添加到容器進行使用


          4,具體說明

          • A創(chuàng)建過程中需要B,于是A將自己放到三級緩存里面,去實例化B

          • B實例化的時候發(fā)現(xiàn)需要A,于是B先查一級緩存,沒有,再查二級緩存,還是沒有,再查三級緩存,找到了A然后把三級緩存里面的這個A放到二級緩存里面,并刪除三級緩存里面的A

          • B順利初始化完畢,將自己放到一級緩存里面(此時B里面的A依然是創(chuàng)建中狀態(tài))然后回來接著創(chuàng)建A,此時B已經(jīng)創(chuàng)建結(jié)束,直接從一級緩存里面拿到B,然后完成創(chuàng)建,并將A放到一級緩存中。


          5,圖解

            


          三、為什么使用三級緩存


          1,使用一級緩存

            實例化A -> 將半成品的A放入singletonObjects中->填充A的屬性時發(fā)現(xiàn)取不到B->實例化B->從singletonObjects中取出A填充B的屬性->將成品B放入singletonObjects->將B填充到A的屬性中->將成品A放入singletonObjects。

            問題:這種基本流程是通的,但是如果在整個流程進行中,有另一個線程要來取A,那么有可能拿到的只是一個屬性都為null的半成品A,這樣就會有問題。


          2,使用二級緩存


          a)使用singletonObjects和earlySingletonObjects

            成品放在singletonObjects中,半成品放在earlySingletonObjects中

            流程可以這樣走:實例化A ->將半成品的A放入earlySingletonObjects中 ->填充A的屬性時發(fā)現(xiàn)取不到B->實例化B->將半成品的A放入earlySingletonObjects中->從earlySingletonObjects中取出A填充B的屬性->將成品B放入singletonObjects,并從earlySingletonObjects中刪除B->將B填充到A的屬性中->將成品A放入singletonObjects并刪除earlySingletonObjects。

            問題:這樣的流程是線程安全的,不過如果A上加個切面(AOP),這種做法就沒法滿足需求了,因為earlySingletonObjects中存放的都是原始對象,而我們需要注入的其實是A的代理對象。

          b)使用singletonObjects和singletonFactories

            成品放在singletonObjects中,半成品通過singletonFactories來獲取

            流程是這樣的:實例化A ->創(chuàng)建A的對象工廠并放入singletonFactories中 ->填充A的屬性時發(fā)現(xiàn)取不到B->實例化B->創(chuàng)建B的對象工廠并放入singletonFactories中->從singletonFactories中獲取A的對象工廠并獲取A填充到B中->將成品B放入singletonObjects,并從singletonFactories中刪除B的對象工廠->將B填充到A的屬性中->將成品A放入singletonObjects并刪除A的對象工廠。

            問題:這樣的流程也適用于普通的IOC,但如果A上加個切面(AOP)的話,這種情況也無法滿足需求,因為每次通過singletonFactories.getObject()獲取的代理對象都不同。






          粉絲福利:Java從入門到入土學(xué)習(xí)路線圖

          ??????

          ??長按上方微信二維碼 2 秒


          感謝點贊支持下哈 

          瀏覽 68
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  不戴套进入让少妇高潮 | 国产精品老熟女视频一区二区 | 六月丁香五月婷婷 | 国产乱人乱偷精品 | 亚洲无码视频日本 |