真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

SpringIOCDI循環(huán)依賴實(shí)例詳解

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

成都創(chuàng)新互聯(lián)公司是一家專注于成都做網(wǎng)站、網(wǎng)站建設(shè)、外貿(mào)營(yíng)銷網(wǎng)站建設(shè)與策劃設(shè)計(jì),新華網(wǎng)站建設(shè)哪家好?成都創(chuàng)新互聯(lián)公司做網(wǎng)站,專注于網(wǎng)站建設(shè)十余年,網(wǎng)設(shè)計(jì)領(lǐng)域的專業(yè)建站公司;建站業(yè)務(wù)涵蓋:新華等地區(qū)。新華做網(wǎng)站價(jià)格咨詢:028-86922220

1、需要知道Bean初始化的兩個(gè)階段

① Bean實(shí)例化創(chuàng)建實(shí)例對(duì)象(new Bean())

② Bean實(shí)例對(duì)象初始化(DI:注解自動(dòng)注入)

2、DefaultSingletonBeanRegistry類中的5個(gè)容器

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

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

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

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

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

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

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

①bean初始化前后會(huì)打標(biāo),加入到singletonsCurrentlyInCreation容器中,這個(gè)打標(biāo)會(huì)在核心方法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表達(dá)式:其實(shí)是調(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)依賴的兩個(gè)打標(biāo)
    //this.earlySingletonObjects.remove(beanName);
    //this.registeredSingletons.add(beanName);放入單例beanName容器中
    addSingleton(beanName, singletonObject);
    ...
    }
  }

② 上面singletonObject = singletonFactory.getObject()時(shí)向singletonFactories中記錄了(new Bean()),singletonFactories也會(huì)在核心方法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);
    //將實(shí)例化bean(①階段)、beanName組裝成singletonFactory裝入singletonFactories容器
    //this.earlySingletonObjects.remove(beanName);
    //刪除earlySingletonObjects中beanName
    addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
    ...
    //實(shí)例初始化 就是在這里面實(shí)現(xiàn)依賴注入DI的:反射實(shí)現(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)依賴核心就在于這個(gè)判斷,由于打標(biāo)+記錄了①階段的bean,
    //循環(huán)依賴第二次調(diào)用getBean("a")時(shí),這里會(huì)直接返回第一次調(diào)用getBean("a")創(chuàng)建的①階段的bean
    //而不會(huì)調(diào)用createBean("a")再次bean初始化(造成兩個(gè)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 doGetBean(final String name, @Nullable final Class 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實(shí)例化后保存到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é)

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

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

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

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

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

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

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持創(chuàng)新互聯(lián)。


本文標(biāo)題:SpringIOCDI循環(huán)依賴實(shí)例詳解
網(wǎng)站地址:http://weahome.cn/article/jjohds.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部