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中。
