最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringIOC DI循環(huán)依賴實例詳解

 更新時間:2020年03月06日 13:35:23   作者:FFStayF  
這篇文章主要介紹了SpringIOC——DI循環(huán)依賴,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下

要弄清楚循環(huán)依賴

1、需要知道Bean初始化的兩個階段

① Bean實例化創(chuàng)建實例對象(new Bean())

② Bean實例對象初始化(DI:注解自動注入)

2、DefaultSingletonBeanRegistry類中的5個容器

/** 記錄已將創(chuàng)建的單例<beanName,singletonBean> */
  private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

  /** 記錄singletonFactory<beanName,singletonFactory> singeletonFactory中存放beanName和上面的①階段的bean:Bean實例化實例對象(還未初始化DI)*/
  private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

  /** 記錄早期的singletonBean 存放的也是① */
  private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

  /** 存放已經(jīng)初始化后的beanName,有序 */
  private final Set<String> registeredSingletons = new LinkedHashSet<>(256);

  /** 記錄正在初始化的bean的beanName */
  private final Set<String> singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));

其中跟循環(huán)依賴相關(guān)的是singletonFactories、singeletonsCurrentlyInCreation、earlysingletonObjects.

3、循環(huán)依賴實現(xiàn)

①bean初始化前后會打標(biāo),加入到singletonsCurrentlyInCreation容器中,這個打標(biāo)會在核心方法getSingleton()中起作用

/* org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, org.springframework.beans.factory.ObjectFactory<?>) */
  public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    ...
    //循環(huán)依賴相關(guān):初始化前先singletonsCurrentlyInCreation.add(beanName)
    beforeSingletonCreation(beanName);
    ...
    //lamda表達式:其實是調(diào)用createBean(beanName, mbd, args):Bean初始化
    singletonObject = singletonFactory.getObject();
    ...
    //循環(huán)依賴相關(guān):初始化后singletonsCurrentlyInCreation.remove(beanName)
    afterSingletonCreation(beanName);
    ...//初始化完后
    //this.singletonObjects.put(beanName, singletonObject);放入到單例容器中
    //this.singletonFactories.remove(beanName);清空循環(huán)依賴的兩個打標(biāo)
    //this.earlySingletonObjects.remove(beanName);
    //this.registeredSingletons.add(beanName);放入單例beanName容器中
    addSingleton(beanName, singletonObject);
    ...
    }
  }

② 上面singletonObject = singletonFactory.getObject()時向singletonFactories中記錄了(new Bean()),singletonFactories也會在核心方法getSingleton()中起作用

/* org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean */
  protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
      throws BeanCreationException {
    ...
    //循環(huán)依賴相關(guān)邏輯:
    //this.singletonFactories.put(beanName, singletonFactory);
    //將實例化bean(①階段)、beanName組裝成singletonFactory裝入singletonFactories容器
    //this.earlySingletonObjects.remove(beanName);
    //刪除earlySingletonObjects中beanName
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    ...
    //實例初始化 就是在這里面實現(xiàn)依賴注入DI的:反射實現(xiàn)
    //調(diào)用AutowiredAnnotationBeanPostProcessor.postProcessProperties
    populateBean(beanName, mbd, instanceWrapper);
    ...
  }

③ 核心方法getSingleton

/* org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean) */
  protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    Object singletonObject = this.singletonObjects.get(beanName);
     //循環(huán)依賴核心就在于這個判斷,由于打標(biāo)+記錄了①階段的bean,
    //循環(huán)依賴第二次調(diào)用getBean("a")時,這里會直接返回第一次調(diào)用getBean("a")創(chuàng)建的①階段的bean
    //而不會調(diào)用createBean("a")再次bean初始化(造成兩個bean的循環(huán)創(chuàng)建)
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
      synchronized (this.singletonObjects) {
        singletonObject = this.earlySingletonObjects.get(beanName);
        if (singletonObject == null && allowEarlyReference) {
          ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
          if (singletonFactory != null) {
            singletonObject = singletonFactory.getObject();
            this.earlySingletonObjects.put(beanName, singletonObject);
            this.singletonFactories.remove(beanName);
          }
        }
      }
    }
    return singletonObject;
  }

④ 循環(huán)依賴流程

/* org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean */
  protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
      @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
    ...
    //假設(shè)A、B互相依賴
    //第一次getBean(A),sharedInstance == null,走else,createBean
    //A正在創(chuàng)建打標(biāo),①中beforeSingletonCreation()
    //A實例化后保存到singletonFactories中②中addSingletonFactory(beanName,singletonFactory)
    //DI依賴注入:②中populateBean(beanName,mbd,instanceWrapper),發(fā)現(xiàn)依賴B,調(diào)用getBean(B)初始化B的單例
    //調(diào)用getBean(B)重復(fù)上面步驟,DI依賴注入發(fā)現(xiàn)依賴A,調(diào)用getBean(A)
    //第二次getBean(A),③中if(singletonObject == null && isSingletonCurrentlyInCreation(A))由于打標(biāo)了所以返回singleFactory.getObject()
    //下面if條件直接返回bean,沒有走else破壞了循環(huán)
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
      //
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    else {
      ...
      //
      createBean(beanName, mbd, args);
      bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }
    return bean;      
  }

四、總結(jié)

未看源碼之前,其實對循環(huán)依賴有一個想法:循環(huán)依賴可以看做是一個死鎖。

預(yù)防死鎖的方法:打破死鎖的四個必要條件(互斥、請求并等待、不可剝奪、循環(huán)等待),由于循環(huán)依賴的資源是對象自身,所以常用破壞循環(huán)等待條件方法:編號順序執(zhí)行,不適用

選擇破壞請求并等待條件:先創(chuàng)建對象,再賦值,模型

A a = new A();
B b = new B();
A.b = b;
B.a = a;

研究源碼之后發(fā)現(xiàn):想法差不多,但是代碼實現(xiàn)非常精彩。模型(打標(biāo)沒想到過)

A a = new A();
B b = new B();
b.a = a;
a.b = b;

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 利用Spring Boot操作MongoDB的方法教程

    利用Spring Boot操作MongoDB的方法教程

    mongodb是最早熱門非關(guān)系數(shù)據(jù)庫的之一,使用也比較普遍,一般會用做離線數(shù)據(jù)分析來使用,放到內(nèi)網(wǎng)的居多,下面這篇文章主要給大家介紹了利用Spring Boot操作MongoDB的方法教程,需要的朋友可以參考下
    2017-05-05
  • spring boot里增加表單驗證hibernate-validator并在freemarker模板里顯示錯誤信息(推薦)

    spring boot里增加表單驗證hibernate-validator并在freemarker模板里顯示錯誤信息(推

    這篇文章主要介紹了spring boot里增加表單驗證hibernate-validator并在freemarker模板里顯示錯誤信息的相關(guān)資料,需要的朋友可以參考下
    2018-01-01
  • SpringBoot實現(xiàn)動態(tài)增刪啟停定時任務(wù)的方式

    SpringBoot實現(xiàn)動態(tài)增刪啟停定時任務(wù)的方式

    在spring?boot中,可以通過@EnableScheduling注解和@Scheduled注解實現(xiàn)定時任務(wù),也可以通過SchedulingConfigurer接口來實現(xiàn)定時任務(wù),但是這兩種方式不能動態(tài)添加、刪除、啟動、停止任務(wù),本文給大家介紹SpringBoot實現(xiàn)動態(tài)增刪啟停定時任務(wù)的方式,感興趣的朋友一起看看吧
    2024-03-03
  • Java生產(chǎn)者消費者的三種實現(xiàn)方式

    Java生產(chǎn)者消費者的三種實現(xiàn)方式

    這篇文章主要介紹了Java生產(chǎn)者消費者的三種實現(xiàn)方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Java?EasyExcel實現(xiàn)合并相同內(nèi)容單元格與動態(tài)標(biāo)題功能

    Java?EasyExcel實現(xiàn)合并相同內(nèi)容單元格與動態(tài)標(biāo)題功能

    這篇文章主要為大家詳細介紹了Java?EasyExcel如何實現(xiàn)合并相同內(nèi)容單元格與動態(tài)標(biāo)題功能,文中的示例代碼講解詳細,有需要的小伙伴可以參考下
    2023-12-12
  • Java簡單實現(xiàn)定時器

    Java簡單實現(xiàn)定時器

    這篇文章主要為大家詳細介紹了Java簡單實現(xiàn)定時器,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • Java中import導(dǎo)入的用法說明

    Java中import導(dǎo)入的用法說明

    這篇文章主要介紹了Java中import導(dǎo)入的用法說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Maven Assembly實戰(zhàn)教程

    Maven Assembly實戰(zhàn)教程

    MavenAssembly插件用于創(chuàng)建可分發(fā)包,如JAR、ZIP或TAR文件,通過配置pom.xml,可以生成包含所有依賴的JAR文件或自定義格式的歸檔文件,示例展示了如何使用默認(rèn)描述符和自定義描述符創(chuàng)建JAR包,以及在多模塊項目中使用Assembly插件
    2024-12-12
  • IDEA Project不顯示/缺失文件問題及解決

    IDEA Project不顯示/缺失文件問題及解決

    在側(cè)邊欄的project模式下,如果發(fā)現(xiàn)缺少部分文件,可以嘗試關(guān)閉項目,打開項目所在目錄,刪除目錄下的.idea文件夾,然后重新打開項目即可解決
    2024-11-11
  • Hibernate實現(xiàn)many-to-many的映射關(guān)系

    Hibernate實現(xiàn)many-to-many的映射關(guān)系

    今天小編就為大家分享一篇關(guān)于Hibernate實現(xiàn)many-to-many的映射關(guān)系,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03

最新評論

泰和县| 龙海市| 尤溪县| 眉山市| 法库县| 始兴县| 安乡县| 康乐县| 信宜市| 金阳县| 梅州市| 临泽县| 分宜县| 龙海市| 洪泽县| 双城市| 五河县| 溆浦县| 尉氏县| 富源县| 宜兰市| 焉耆| 康乐县| 元朗区| 西吉县| 浙江省| 溆浦县| 无锡市| 台北市| 东源县| 绵竹市| 陈巴尔虎旗| 哈尔滨市| 邯郸县| 台北县| 古蔺县| 平顺县| 嘉峪关市| 南安市| 轮台县| 鹤岗市|