Spring框架05-IoC循環依賴

Spring IoC 循環依賴問題

什麼是循環依賴

循環依賴其實就是循環引⽤,也就是兩個或者兩個以上的 Bean互相持有對⽅,最終造成閉環。⽐如A 依賴於B,B依賴於C,C⼜依賴於A
image.pngjava

注意,這⾥不是函數的循環調⽤,是對象的相互依賴關係。循環調⽤其實就是⼀個死循環,除⾮有終結條件spring

Spring中循環依賴場景有:ide

  • 構造器的循環依賴(構造器注⼊)
  • Field屬性的循環依賴(set注⼊)
其中,構造器的循環依賴問題⽆法解決,只能拋出 BeanCurrentlyInCreationException異常,在解決屬性循環依賴時,spring採⽤的是提早暴露對象的⽅法

循環依賴處理機制

  • 單例 bean 構造器參數循環依賴(⽆法解決)
  • prototype 原型 bean循環依賴(⽆法解決)
    對於原型bean的初始化過程當中不管是經過構造器參數循環依賴仍是經過set⽅法產⽣循環依賴,Spring都 會直接報錯處理。

單例bean經過setXxx或者@Autowired進⾏循環依賴

image.png

Spring的循環依賴的理論依據基於Java的引⽤傳遞,當得到對象的引⽤時,對象的屬性是能夠延後設置的,可是構造器必須是在獲取引⽤以前函數

Spring經過setXxx或者@Autowired⽅法解決循環依賴實際上是經過提早暴露⼀個ObjectFactory對象來完成的,簡單來講ClassA在調⽤構造器完成對象初始化以後,在調⽤ClassA的setClassB⽅法以前就把ClassA實例化的對象經過ObjectFactory提早暴露到Spring容器中this

boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&

isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) {

if (logger.isDebugEnabled()) {

logger.debug("Eagerly caching bean '" + beanName +

"' to allow for resolving potential circular references");

}

//將初始化後的對象提早已ObjectFactory對象注⼊到容器中addSingletonFactory(beanName, new ObjectFactory<Object>() {

@Override

public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd,bean);

}

});
  • Spring容器初始化ClassA經過構造器初始化對象後提早暴露到Spring容器
  • ClassA調⽤setClassB⽅法,Spring⾸先嚐試從容器中獲取ClassB,此時ClassB不存在Spring容器中
  • Spring容器初始化ClassB,同時也會將ClassB提早暴露到Spring容器中
  • ClassB調⽤setClassA⽅法,Spring從容器中獲取ClassA ,由於第⼀步中已經提早暴露了ClassA,所以能夠獲取到ClassA實例spa

    • ClassA經過spring容器獲取到ClassB,完成了對象初始化操做
  • 這樣ClassA和ClassB都完成了對象初始化操做,解決了循環依賴問題
相關文章
相關標籤/搜索