javascript
Spring bean的生命流程
2019獨角獸企業重金招聘Python工程師標準>>>
Spring 是一個輕量級的 J2EE 開源框架,其目標是降低企業級應用開發難度,提高企業級應用開發效率。在日程開發中,我們會經常使用 Spring 框架去構建應用。所以作為一個經常使用的框架,了解其原理還是很有必要的。接下來我們就從宏觀層面上,來看看 Spring 中的 bean 由實例化到銷毀的過程。在詳細討論 bean 生命周期前,先上一張圖,后面也會圍繞這張圖展開討論。
圖1 bean實例化過程
接下來對照上圖,一步一步對 singleton 類型 bean 的生命周期進行解析:
上述流程從宏觀上對 Spring 中 singleton 類型 bean 的生命周期進行了描述,接下來說說所上面流程中的一些細節問題。
先看流程中的第二步 -- 設置對象屬性。在這一步中,對于普通類型的屬性,例如 String,Integer等,比較容易處理,直接設置即可。但是如果某個 bean 對象依賴另一個 bean 對象,此時就不能直接設置了。Spring 容器首先要先去實例化 bean 依賴的對象,實例化好后才能設置到當前 bean 中。大致流程如下:
圖2 依賴實例化流程圖
上面圖片描述的依賴比較簡單,就是 BeanA 依賴 BeanB。現在考慮這樣一種情況,BeanA 依賴 BeanB,BeanB 依賴 BeanC,BeanC 又依賴 BeanA。三者形成了循環依賴,如下所示:
圖3 循環依賴
對于這樣的循環依賴,根據依賴注入方式的不同,Spring 處理方式也不同。如果依賴靠構造器方式注入,則無法處理,Spring 直接會報循環依賴異常。這個理解起來也不復雜,構造 BeanA 時需要 BeanB 作為構造器參數,此時 Spring 容器會先實例化 BeanB。構造 BeanB 時,BeanB 又需要 BeanC 作為構造器參數,Spring 容器又不得不先去構造 BeanC。最后構造 BeanC 時,BeanC 又依賴 BeanA 才能完成構造。此時,BeanA 還沒構造完成,BeanA 要等 BeanB 實例化好才能完成構造,BeanB 又要等 BeanC,BeanC 等 BeanA。這樣就形成了死循環,所以對于以構造器注入方式的循環依賴是無解的,Spring 容器會直接報異常。對于 setter 類型注入的循環依賴則可以順利完成實例化并依次注入,這里具體細節就不說了,詳細可以參考《Spring源碼深度解析》一書相關章節。
循環依賴問題說完,接下來 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 織入流程,大致如下:
大家現在應該知道 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。
本篇博客到此結束,如果有寫錯的地方,歡迎指出來,謝謝!如果錯誤的地方對你造成了困擾,我表示很抱歉。
參考?:
- 《Spring揭秘》
- 《Spring源碼深度解析》
- https://www.zybuluo.com/dugu9sword/note/382745
轉載于:https://my.oschina.net/u/2935389/blog/3032887
總結
以上是生活随笔為你收集整理的Spring bean的生命流程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Apache HBase的现状和发展
- 下一篇: 匿名内部类,就是内部类的简写格式。