天天看點

spring處理對象互相依賴注入的問題

版權聲明:本文為部落客原創文章,未經部落客允許不得轉載。 https://blog.csdn.net/w1lgy/article/details/81086171

最近重新再看spring的内容的時候有個疑問:當spring對象對象存在互相依賴注入的時候,會不會造成死循環,如果不會spring是怎麼解決的?帶着這個疑問我自己在eclipse試了一下,發現是能正常運作的,那麼spring是怎麼做到的呢,帶着疑問我百度了一下,查到一篇部落格可供大家參考:

https://blog.csdn.net/u012410733/article/details/61062858 。但是這篇部落格并不能完全解決的疑問,于是我又把問題發給了線上教育訓練的導師和教育訓練的會員群上,經過老師的解讀加上我查閱資料,做出以下總結:

一、Spring 循環依賴需要滿足三個條件:

1、setter 注入(構造器注入不能循環依賴)

2、singleton bean(非單例 bean 不支援)

3、AbstractAutowireCapableBeanFactory#allowCircularReferences 這個 boolean 屬性控制是否可以循環,預設為 true。

二、Spring 建立對象分為三個過程:

1、建立對象執行個體 Object obj = new Object() 或者 Object obj = new Object(xxx);

AbstractAutowireCapableBeanFactory#createBeanInstance

2、依賴注入: obj.setXxx(xxx) {多個屬性就是 foreach}

AbstractAutowireCapableBeanFactory#populateBean

3、Spring bean 擴充方法:init-method,BeanPostProcess,XXXAware 擴充

AbstractAutowireCapableBeanFactory#initializeBean

實作原理:

我們知道在循環依賴當中其實就是多個 bean 調用 BeanFactory#getBean

具體實作在 org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

而這個方在 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean 方法前。

首先來看一下 AbstractBeanFactory#doGetBean

在進入 doGetBean 方法時就會從緩存裡面拿 beanName 對應的對象。

其實中就包含建立的 ObjectFactory

總結

互相依賴:A 依賴 B, B 依賴 A

當 A 建立的時候,會把 A 對應的 ObjectFactory 放在緩存中,當依賴注入的時候發現了 B 對象,調用 getBean() 方法擷取 B 對象, 然後建立 B 對象,會把 B 對應的 ObjectFactory 放在緩存中。

此時 B 依賴 A ,然後再調用 getBean 擷取 A 對象, 此時調用 AbstractBeanFactory#doGetBean 從緩存中擷取到 A 對應的 ObjectFactory。

這樣就避免了死循環,然後再建立成功之後删除 ObjectFactory 完成依賴注入。

思路:中間對象去解決循環依賴。

繼續閱讀