回覆列表
  • 1 # 程式設計師阿照

    spring是如何解決單例的迴圈依賴注入

    首先看下面三個快取:

    1.singletonObjects:存放初始化好的bean

    2.earlySingletonObjects:存放了剛例項化好的,但是還未配置屬性和初始化的bean,我們在獲取該bean的時候會呼叫beanPostProcessor的getEarlyReference進行一些提前獲取bean的必要操作

    3.singletonFactories:存放我剛例項化的bean,透過ObjectFactory,可以讓如果有提前需要bean的需要可以呼叫該

    objectfactory 其會將剛例項化好的bean經過beanPostProcessor的getEarlyReference處理進行返回

    我們先例項化A,例項化好後

    呼叫addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

    () -> getEarlyBeanReference(beanName, mbd, bean)是objectFactory的實現匿名類,然後此時我們設定屬性的時候會發現我們還依賴B,於是我們去例項化B而當我們此時例項化B的會經過下面這個方法

    protected Object getSingleton(String beanName, boolean allowEarlyReference) {

    首先從singletonObjects獲取是否存在以及初始化好的bean

    Object singletonObject = this.singletonObjects.get(beanName);

    如果沒有,且依賴的A正在初始化,那我們去嘗試看看earlySingletonObjects是否有物件

    earlySingletonObjects存放的是還未例項化好物件

    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {

    因為我們初始化bean都是加鎖的,但是這邊的鎖對於迴圈依賴是沒用的,因為我們都是例項化好物件

    準備設定屬性的時候才發現迴圈依賴這個時候再去建立依賴物件,都是同一個執行緒此時鎖是可重入的

    synchronized (this.singletonObjects) {

    從earlySingletonObjects獲取

    singletonObject = this.earlySingletonObjects.get(beanName);

    獲取不到 但是支援獲取EarlyReference

    if (singletonObject == null && allowEarlyReference) {

    我們獲取objectfactory,這個objectfactory就是

    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));

    中的() -> getEarlyBeanReference(beanName, mbd, bean),然後吧結果放入

    earlySingletonObjects,我們在整個單例建立結束的時候在把正在初始化好的物件放入

    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);

    if (singletonFactory != null) {

    singletonObject = singletonFactory.getObject();

    this.earlySingletonObjects.put(beanName, singletonObject);

    this.singletonFactories.remove(beanName);

    }

    }

    }

    }

    return singletonObject;

    }

    由此可見 如果之前已經把A存放在singletonFactories,那麼B會把其調出來放入earlySingletonObjects,然後整個單例建立完成在塞入singletonObjects。存放在singletonFactories好處是可擴充套件,我們在這個裡面會呼叫beanPostProcessor 從而可以在我們實現提前獲取物件引用的時候進行一些操作

  • 2 # 21Char

    簡單來講,第三級快取是為了解決迴圈依賴的物件是aop代理物件的這種情況,用來提前對早期物件進行動態代理的,這需要你明白aop是怎麼初始化的以後就懂為啥要用三級了,但這是對aop代理這種特殊情況,大部分情況兩級快取足夠了

  • 中秋節和大豐收的關聯?
  • 墨水弄在褲子上怎麼洗掉?