【Spring】 Spring如何解決循環依賴的問題?


https://mp.weixin.qq.com/s/FtbzTMxHgzL0G1R2pSlh-A

通常來說,如果問Spring內部如何解決循環依賴,一定是單默認的單例Bean中,屬性互相引用的場景。比如幾個Bean之間的互相引用:

 

甚至自己“循環”依賴自己:

 

 

 先說明前提:原型(Prototype)的場景是不支持循環依賴的,通常會走到AbstractBeanFactory類中下面的判斷,拋出異常。

if (isPrototypeCurrentlyInCreation(beanName)) {
  throw new BeanCurrentlyInCreationException(beanName);
}

原因很好理解,創建新的A時,發現要注入原型字段B,又創建新的B發現要注入原型字段A...

這就套娃了, 你猜是先StackOverflow還是OutOfMemory?Spring怕你不好猜,就先拋出了BeanCurrentlyInCreationException

基於構造器的循環依賴,就更不用說了,官方文檔都攤牌了,你想讓構造器注入支持循環依賴,是不存在的,不如把代碼改了。那么默認單例的屬性注入場景,Spring是如何支持循環依賴的?

Spring解決循環依賴

首先,Spring內部維護了三個Map,也就是我們通常說的三級緩存。筆者翻閱Spring文檔倒是沒有找到三級緩存的概念,可能也是本土為了方便理解的詞匯。在Spring的DefaultSingletonBeanRegistry類中,你會赫然發現類上方掛着這三個Map:

  • singletonObjects 它是我們最熟悉的朋友,俗稱“單例池”“容器”,緩存創建完成單例Bean的地方。
  • singletonFactories 映射創建Bean的原始工廠
  • earlySingletonObjects 映射Bean的早期引用,也就是說在這個Map里的Bean不是完整的,甚至還不能稱之為“Bean”,只是一個Instance.

后兩個Map其實是“墊腳石”級別的,只是創建Bean的時候,用來借助了一下,創建完成就清掉了。所以筆者前文對“三級緩存”這個詞有些迷惑,可能是因為注釋都是以Cache of開頭吧。為什么成為后兩個Map為墊腳石,假設最終放在singletonObjects的Bean是你想要的一杯“涼白開”。那么Spring准備了兩個杯子,即singletonFactories和earlySingletonObjects來回“倒騰”幾番,把熱水晾成“涼白開”放到singletonObjects中。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM