国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Spring bean的生命流程

趙連江 / 1498人閱讀

摘要:如果依賴靠構造器方式注入,則無法處理,直接會報循環依賴異常。光繼承這個接口還不夠,繼承這個接口只能獲取,要想讓生效,還需要拿到切面對象包含和才行。有了目標對象,所有的切面類,此時就可以為生成代理對象了。

Spring 是一個輕量級的 J2EE 開源框架,其目標是降低企業級應用開發難度,提高企業級應用開發效率。在日程開發中,我們會經常使用 Spring 框架去構建應用。所以作為一個經常使用的框架,了解其原理還是很有必要的。接下來我們就從宏觀層面上,來看看 Spring 中的 bean 由實例化到銷毀的過程。在詳細討論 bean 生命周期前,先上一張圖,后面也會圍繞這張圖展開討論。

圖1 bean實例化過程

接下來對照上圖,一步一步對 singleton 類型 bean 的生命周期進行解析:

實例化 bean 對象,類似于 new XXObject()

將配置文件中配置的屬性填充到剛剛創建的 bean 對象中。

檢查 bean 對象是否實現了 Aware 一類的接口,如果實現了則把相應的依賴設置到 bean 對象中。比如如果 bean 實現了 BeanFactoryAware 接口,Spring 容器在實例化bean的過程中,會將 BeanFactory 容器注入到 bean 中。

調用 BeanPostProcessor 前置處理方法,即 postProcessBeforeInitialization(Object bean, String beanName)。

檢查 bean 對象是否實現了 InitializingBean 接口,如果實現,則調用 afterPropertiesSet 方法。或者檢查配置文件中是否配置了 init-method 屬性,如果配置了,則去調用 init-method 屬性配置的方法。

調用 BeanPostProcessor 后置處理方法,即 postProcessAfterInitialization(Object bean, String beanName)。我們所熟知的 AOP 就是在這里將 Adivce 邏輯織入到 bean 中的。

注冊 Destruction 相關回調方法。

bean 對象處于就緒狀態,可以使用了。

應用上下文被銷毀,調用注冊的 Destruction 相關方法。如果 bean 實現了 DispostbleBean 接口,Spring 容器會調用 destroy 方法。如果在配置文件中配置了 destroy 屬性,Spring 容器則會調用 destroy 屬性對應的方法。

上述流程從宏觀上對 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 織入流程,大致如下:

查找實現了 PointcutAdvisor 類型的切面類,切面類包含了 Pointcut 和 Advice 實現類對象。

檢查 Pointcut 中的表達式是否能匹配當前 bean 對象。

如果匹配到了,表明應該對此對象織入 Advice。

將 bean,bean class對象,bean實現的interface的數組,Advice對象傳給代理工廠 ProxyFactory。代理工廠創建出 AopProxy 實現類,最后由 AopProxy 實現類創建 bean 的代理類,并將這個代理類返回。此時從 postProcessAfterInitialization(Object bean, String beanName) 返回的 bean 此時就不是原來的 bean 了,而是 bean 的代理類。原 bean 就這樣被無感的替換掉了,是不是有點偷天換柱的感覺。

大家現在應該知道 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

本文在知識共享許可協議 4.0 下發布,轉載請注明出處
作者:coolblog
為了獲得更好的分類閱讀體驗,
請移步至本人的個人博客:http://www.coolblog.xyz


本作品采用知識共享署名-非商業性使用-禁止演繹 4.0 國際許可協議進行許可。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/70177.html

相關文章

  • 仿照 Spring 實現簡單 IOC 和 AOP - 下篇

    摘要:在上文中,我實現了一個很簡單的和容器。比如,我們所熟悉的就是在這里將切面邏輯織入相關中的。初始化的工作算是結束了,此時處于就緒狀態,等待外部程序的調用。其中動態代理只能代理實現了接口的對象,而動態代理則無此限制。 1. 背景 本文承接上文,來繼續說說 IOC 和 AOP 的仿寫。在上文中,我實現了一個很簡單的 IOC 和 AOP 容器。上文實現的 IOC 和 AOP 功能很單一,且 I...

    AlexTuan 評論0 收藏0
  • Bean 生命周期回調

    摘要:如果該方法的返回值代替原本該生成的目標對象,后續只有方法會調用,其它方法不再調用否則按照正常的流程走方法在目標對象實例化之后調用,這個時候對象已經被實例化,但是該實例的屬性還未被設置,都是。 我們可能會在 Bean 對象創建完成后, 執行某些操作或在銷毀前做某些操作. 我們可以實現 InitializingBean 或 DisposableBean 接口 public class Te...

    xorpay 評論0 收藏0
  • Learn Spring - Spring IoC

    摘要:事件事件監聽器,對監聽到的事件進行處理。擁有一個成員變量,提供了容器監聽器的注冊表。注冊事件監聽器根據反射機制,使用的方法,從中找出所有實現的,將它們注冊為容器的事件監聽器,實際的操作就是將其添加到事件廣播器所提供的監聽器注冊表中。 1. Spring的資源抽象接口 假如有一個文件位于Web應用的類路徑下,用戶可以通過以下方式對這個文件資源進行訪問: 通過FileSystemReso...

    luzhuqun 評論0 收藏0
  • Spring知識——IOC容器

    摘要:生成的兩種方式通過反射調用構造函數通過優點依賴關系的管理被反轉并交給容器,使復雜的依賴關系管理從應用中解放出來。 IOC概述 1、理解: (1)控制反轉。將生成對象的控制權交IOC容器,由容器生成依賴的對象。調用類只依賴接口,而不依賴具體的實現類,減少了耦合。在運行的時候,才由容器將具體的實例注入到調用類的對象中。(2)依賴注入,就是向Ioc容器索要bean的過程。getBean是依賴...

    yexiaobai 評論0 收藏0
  • spring提供關于bean生命周期接口

    摘要:在中注入注入運行結果注入使用注解正如其名在構造器之后,即在銷毀之前。調用的方法構造器注入屬性注入顧名思義,在這個方法里面可以拿到所有裝載的并在初始化之前對某些進行修改。 先看一張圖:spring4.x 企業實戰 showImg(https://segmentfault.com/img/bVbbO72?w=608&h=502); spring版本:4.3.171、bean自身的生命周期接...

    Cciradih 評論0 收藏0

發表評論

0條評論

趙連江

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<