Spring 是一個輕量級的 J2EE 開源框架,其目標是下降企業級應用開發難度,提升企業級應用開發效率。在日程開發中,咱們會常用 Spring 框架去構建應用。因此做爲一個常用的框架,瞭解其原理仍是頗有必要的。接下來咱們就從宏觀層面上,來看看 Spring 中的 bean 由實例化到銷燬的過程。在詳細討論 bean 生命週期前,先上一張圖,後面也會圍繞這張圖展開討論。java
圖1 bean實例化過程git
接下來對照上圖,一步一步對 singleton 類型 bean 的生命週期進行解析:github
上述流程從宏觀上對 Spring 中 singleton 類型 bean 的生命週期進行了描述,接下來講說所上面流程中的一些細節問題。
先看流程中的第二步 -- 設置對象屬性。在這一步中,對於普通類型的屬性,例如 String,Integer等,比較容易處理,直接設置便可。可是若是某個 bean 對象依賴另外一個 bean 對象,此時就不能直接設置了。Spring 容器首先要先去實例化 bean 依賴的對象,實例化好後才能設置到當前 bean 中。大體流程以下:
spring
圖2 依賴實例化流程圖數組
上面圖片描述的依賴比較簡單,就是 BeanA 依賴 BeanB。如今考慮這樣一種狀況,BeanA 依賴 BeanB,BeanB 依賴 BeanC,BeanC 又依賴 BeanA。三者造成了循環依賴,以下所示:框架
圖3 循環依賴post
對於這樣的循環依賴,根據依賴注入方式的不一樣,Spring 處理方式也不一樣。若是依賴靠構造器方式注入,則沒法處理,Spring 直接會報循環依賴異常。這個理解起來也不復雜,構造 BeanA 時須要 BeanB 做爲構造器參數,此時 Spring 容器會先實例化 BeanB。構造 BeanB 時,BeanB 又須要 BeanC 做爲構造器參數,Spring 容器又不得不先去構造 BeanC。最後構造 BeanC 時,BeanC 又依賴 BeanA 才能完成構造。此時,BeanA 還沒構造完成,BeanA 要等 BeanB 實例化好才能完成構造,BeanB 又要等 BeanC,BeanC 等 BeanA。這樣就造成了死循環,因此對於以構造器注入方式的循環依賴是無解的,Spring 容器會直接報異常。對於 setter 類型注入的循環依賴則能夠順利完成實例化並依次注入,這裏具體細節就不說了,詳細能夠參考《Spring源碼深度解析》一書相關章節。spa
循環依賴問題說完,接下來 bean 實例化流程中的第6步 -- 調用 BeanPostProcessor 後置處理方法。先介紹一下 BeanPostProcessor 接口,BeanPostProcessor 接口中包含了兩個方法,其定義以下:代理
public interface BeanPostProcessor { Object postProcessBeforeInitialization(Object bean, String beanName) throws Exception; Object postProcessAfterInitialization(Object bean, String beanName) throws Exception; }
BeanPostProcessor 是一個頗有用的接口,經過實現接口咱們就能夠插手 bean 的實例化過程,爲拓展提供了可能。咱們所熟知的 AOP 就是在這裏進行織如入,具體點說是在 postProcessAfterInitialization(Object bean, String beanName) 執行織入邏輯的。下面就來講說 Spring AOP 織入的流程,以及 AOP 是怎樣和 IOC 整合的。先說 Spring AOP 織入流程,大體以下:code
你們如今應該知道 AOP 是怎樣做用在 bean 上的了,那麼 AOP 是怎樣和 IOC 整合起來並協同工做的呢?下面就來簡單說一下。
Spring AOP 生成代理類的邏輯是在 AbstractAutoProxyCreator 相關子類中實現的,好比 DefaultAdvisorAutoProxyCreator、AspectJAwareAdvisorAutoProxyCreator 等。上面說了 BeanPostProcessor 爲拓展留下了可能,這裏 AbstractAutoProxyCreator 就將可能變爲了現實。AbstractAutoProxyCreator 實現了 BeanPostProcessor 接口,這樣 AbstractAutoProxyCreator 能夠在 bean 初始化時作一些事情。光繼承這個接口還不夠,繼承這個接口只能獲取 bean,要想讓 AOP 生效,還須要拿到切面對象(包含 Pointcut 和 Advice)才行。因此 AbstractAutoProxyCreator 同時繼承了 BeanFactoryAware 接口,經過實現該接口,AbstractAutoProxyCreator 子類就可拿到 BeanFactory,有了 BeanFactory,就能夠獲取 BeanFactory 中全部的切面對象了。有了目標對象 bean,全部的切面類,此時就能夠爲 bean 生成代理對象了。
圖4 AbstractAutoProxyCreator繼承圖(刪掉了一些不關心的繼承分支)
到這裏,從宏觀上已經對 bean 的生命流程進行了較爲詳細的描述。因爲暫時能力有限,只能從宏觀上分析,之前嘗試過去看 Spring IOC 的實現代碼,感受仍是太複雜了,細節太多,跟蹤了十幾二十個方法後就開始凌亂了。在幾回失敗的嘗試後,終於放棄了。後來總結了一下失敗的緣由,當時本身剛工做不是好久,代碼寫的少,經驗不足。而且在對 Spring 不少特性不熟悉的狀況下就去看 Spring 源碼,結果只能處處碰壁,陷入 Spring 各類細節之中久久不能自拔?。因此對於想看某個框架代碼的同窗,必定要在熟練使用這個框架的基礎上再去看。不要像我這樣急於求成,否則到最後只能失敗啊。本人這篇博客創建在仿寫了 Spring IOC 和 AOP的基礎上寫出來的,在仿寫過程當中參考了黃億華前輩的 tiny-spring 項目,有興趣的同窗能夠讀讀 tiny-spring。我本身仿寫的項目也放在了github上,傳送門 --> toy-spring。
本篇博客到此結束,若是有寫錯的地方,歡迎指出來,謝謝!若是錯誤的地方對你形成了困擾,我表示很抱歉。
參考 :
本文在知識共享許可協議 4.0 下發布,轉載請註明出處
做者:coolblog
爲了得到更好的分類閱讀體驗,
請移步至本人的我的博客: http://www.coolblog.xyz
本做品採用知識共享署名-非商業性使用-禁止演繹 4.0 國際許可協議進行許可。