亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

Spring bean的生命流程

趙連江 / 1565人閱讀

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

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

圖1 bean實例化過程

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

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

將配置文件中配置的屬性填充到剛剛創(chuàng)建的 bean 對象中。

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

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

檢查 bean 對象是否實現(xiàn)了 InitializingBean 接口,如果實現(xiàn),則調(diào)用 afterPropertiesSet 方法?;蛘邫z查配置文件中是否配置了 init-method 屬性,如果配置了,則去調(diào)用 init-method 屬性配置的方法。

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

注冊 Destruction 相關(guān)回調(diào)方法。

bean 對象處于就緒狀態(tài),可以使用了。

應(yīng)用上下文被銷毀,調(diào)用注冊的 Destruction 相關(guān)方法。如果 bean 實現(xiàn)了 DispostbleBean 接口,Spring 容器會調(diào)用 destroy 方法。如果在配置文件中配置了 destroy 屬性,Spring 容器則會調(diào)用 destroy 屬性對應(yīng)的方法。

上述流程從宏觀上對 Spring 中 singleton 類型 bean 的生命周期進行了描述,接下來說說所上面流程中的一些細節(jié)問題。
先看流程中的第二步 -- 設(shè)置對象屬性。在這一步中,對于普通類型的屬性,例如 String,Integer等,比較容易處理,直接設(shè)置即可。但是如果某個 bean 對象依賴另一個 bean 對象,此時就不能直接設(shè)置了。Spring 容器首先要先去實例化 bean 依賴的對象,實例化好后才能設(shè)置到當前 bean 中。大致流程如下:

圖2 依賴實例化流程圖

上面圖片描述的依賴比較簡單,就是 BeanA 依賴 BeanB。現(xiàn)在考慮這樣一種情況,BeanA 依賴 BeanB,BeanB 依賴 BeanC,BeanC 又依賴 BeanA。三者形成了循環(huán)依賴,如下所示:

圖3 循環(huán)依賴

對于這樣的循環(huán)依賴,根據(jù)依賴注入方式的不同,Spring 處理方式也不同。如果依賴靠構(gòu)造器方式注入,則無法處理,Spring 直接會報循環(huán)依賴異常。這個理解起來也不復(fù)雜,構(gòu)造 BeanA 時需要 BeanB 作為構(gòu)造器參數(shù),此時 Spring 容器會先實例化 BeanB。構(gòu)造 BeanB 時,BeanB 又需要 BeanC 作為構(gòu)造器參數(shù),Spring 容器又不得不先去構(gòu)造 BeanC。最后構(gòu)造 BeanC 時,BeanC 又依賴 BeanA 才能完成構(gòu)造。此時,BeanA 還沒構(gòu)造完成,BeanA 要等 BeanB 實例化好才能完成構(gòu)造,BeanB 又要等 BeanC,BeanC 等 BeanA。這樣就形成了死循環(huán),所以對于以構(gòu)造器注入方式的循環(huán)依賴是無解的,Spring 容器會直接報異常。對于 setter 類型注入的循環(huán)依賴則可以順利完成實例化并依次注入,這里具體細節(jié)就不說了,詳細可以參考《Spring源碼深度解析》一書相關(guān)章節(jié)。

循環(huán)依賴問題說完,接下來 bean 實例化流程中的第6步 -- 調(diào)用 BeanPostProcessor 后置處理方法。先介紹一下 BeanPostProcessor 接口,BeanPostProcessor 接口中包含了兩個方法,其定義如下:

public interface BeanPostProcessor {

    Object postProcessBeforeInitialization(Object bean, String beanName) throws Exception;

    Object postProcessAfterInitialization(Object bean, String beanName) throws Exception;
}

BeanPostProcessor 是一個很有用的接口,通過實現(xiàn)接口我們就可以插手 bean 的實例化過程,為拓展提供了可能。我們所熟知的 AOP 就是在這里進行織如入,具體點說是在 postProcessAfterInitialization(Object bean, String beanName) 執(zhí)行織入邏輯的。下面就來說說 Spring AOP 織入的流程,以及 AOP 是怎樣和 IOC 整合的。先說 Spring AOP 織入流程,大致如下:

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

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

如果匹配到了,表明應(yīng)該對此對象織入 Advice。

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

大家現(xiàn)在應(yīng)該知道 AOP 是怎樣作用在 bean 上的了,那么 AOP 是怎樣和 IOC 整合起來并協(xié)同工作的呢?下面就來簡單說一下。

Spring AOP 生成代理類的邏輯是在 AbstractAutoProxyCreator 相關(guān)子類中實現(xiàn)的,比如 DefaultAdvisorAutoProxyCreator、AspectJAwareAdvisorAutoProxyCreator 等。上面說了 BeanPostProcessor 為拓展留下了可能,這里 AbstractAutoProxyCreator 就將可能變?yōu)榱爽F(xiàn)實。AbstractAutoProxyCreator 實現(xiàn)了 BeanPostProcessor 接口,這樣 AbstractAutoProxyCreator 可以在 bean 初始化時做一些事情。光繼承這個接口還不夠,繼承這個接口只能獲取 bean,要想讓 AOP 生效,還需要拿到切面對象(包含 Pointcut 和 Advice)才行。所以 AbstractAutoProxyCreator 同時繼承了 BeanFactoryAware 接口,通過實現(xiàn)該接口,AbstractAutoProxyCreator 子類就可拿到 BeanFactory,有了 BeanFactory,就可以獲取 BeanFactory 中所有的切面對象了。有了目標對象 bean,所有的切面類,此時就可以為 bean 生成代理對象了。

圖4 AbstractAutoProxyCreator繼承圖(刪掉了一些不關(guān)心的繼承分支)

到這里,從宏觀上已經(jīng)對 bean 的生命流程進行了較為詳細的描述。由于暫時能力有限,只能從宏觀上分析,以前嘗試過去看 Spring IOC 的實現(xiàn)代碼,感覺還是太復(fù)雜了,細節(jié)太多,跟蹤了十幾二十個方法后就開始凌亂了。在幾次失敗的嘗試后,終于放棄了。后來總結(jié)了一下失敗的原因,當時自己剛工作不是很久,代碼寫的少,經(jīng)驗不足。并且在對 Spring 很多特性不熟悉的情況下就去看 Spring 源碼,結(jié)果只能到處碰壁,陷入 Spring 各種細節(jié)之中久久不能自拔?。所以對于想看某個框架代碼的同學,一定要在熟練使用這個框架的基礎(chǔ)上再去看。不要像我這樣急于求成,不然到最后只能失敗啊。本人這篇博客建立在仿寫了 Spring IOC 和 AOP的基礎(chǔ)上寫出來的,在仿寫過程中參考了黃億華前輩的 tiny-spring 項目,有興趣的同學可以讀讀 tiny-spring。我自己仿寫的項目也放在了github上,傳送門 --> toy-spring。

本篇博客到此結(jié)束,如果有寫錯的地方,歡迎指出來,謝謝!如果錯誤的地方對你造成了困擾,我表示很抱歉。

參考

《Spring揭秘》

《Spring源碼深度解析》

https://www.zybuluo.com/dugu9sword/note/382745

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


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

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/70177.html

相關(guān)文章

  • 仿照 Spring 實現(xiàn)簡單 IOC 和 AOP - 下篇

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

    AlexTuan 評論0 收藏0
  • Bean 生命周期回調(diào)

    摘要:如果該方法的返回值代替原本該生成的目標對象,后續(xù)只有方法會調(diào)用,其它方法不再調(diào)用否則按照正常的流程走方法在目標對象實例化之后調(diào)用,這個時候?qū)ο笠呀?jīng)被實例化,但是該實例的屬性還未被設(shè)置,都是。 我們可能會在 Bean 對象創(chuàng)建完成后, 執(zhí)行某些操作或在銷毀前做某些操作. 我們可以實現(xiàn) InitializingBean 或 DisposableBean 接口 public class Te...

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

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

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

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

    yexiaobai 評論0 收藏0
  • spring提供關(guān)于bean生命周期接口

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

    Cciradih 評論0 收藏0

發(fā)表評論

0條評論

趙連江

|高級講師

TA的文章

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