1. 程式人生 > >Spring解決迴圈依賴,你真的懂了嗎?

Spring解決迴圈依賴,你真的懂了嗎?

## 導讀 - 前幾天發表的文章[SpringBoot多資料來源動態切換](https://chenjiabing666.github.io/2020/03/12/SpringBoot%E6%95%B4%E5%90%88%E5%A4%9A%E6%95%B0%E6%8D%AE%E6%BA%90%EF%BC%8C%E4%BD%A0%E4%BC%9A%E4%BA%86%E5%90%97%EF%BC%9F/)和[SpringBoot整合多資料來源的巨坑](https://chenjiabing666.github.io/2020/03/18/SpringBoot%E6%95%B4%E5%90%88%E5%A4%9A%E6%95%B0%E6%8D%AE%E6%BA%90%E7%9A%84%E5%B7%A8%E5%9D%91/)中,提到了一個坑就是動態資料來源新增@Primary介面就會造成迴圈依賴異常,如下圖: ![微信所有碼猿技術專欄](https://gitee.com/chenjiabing666/Blog-file/raw/master/circleex.png) - 這個就是典型的構造器依賴,詳情請看上面兩篇文章,這裡不再詳細贅述了。本篇文章將會從原始碼深入解析Spring是如何解決迴圈依賴的?為什麼不能解決構造器的迴圈依賴? ## 什麼是迴圈依賴 - 簡單的說就是A依賴B,B依賴C,C依賴A這樣就構成了迴圈依賴。 ![微信搜尋碼猿技術專欄](https://gitee.com/chenjiabing666/Blog-file/raw/master/15282870029143.jpg) - 迴圈依賴分為構造器依賴和屬性依賴,眾所周知的是Spring能夠解決屬性的迴圈依賴(set注入)。下文將從原始碼角度分析Spring是如何解決屬性的迴圈依賴。 ## 思路 - 如何解決迴圈依賴,Spring主要的思路就是依據三級快取,在例項化A時呼叫doGetBean,發現A依賴的B的例項,此時呼叫doGetBean去例項B,例項化的B的時候發現又依賴A,如果不解決這個迴圈依賴的話此時的doGetBean將會無限迴圈下去,導致記憶體溢位,程式奔潰。spring引用了一個早期物件,並且把這個"早期引用"並將其注入到容器中,讓B先完成例項化,此時A就獲取B的引用,完成例項化。 ## 三級快取 - Spring能夠輕鬆的解決屬性的迴圈依賴正式用到了三級快取,在AbstractBeanFactory中有詳細的註釋。 ```java /**一級快取,用於存放完全初始化好的 bean,從該快取中取出的 bean 可以直接使用*/ private f