成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Spring bean的生命流程

趙連江 / 1502人閱讀

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

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

圖1 bean實(shí)例化過(guò)程

接下來(lái)對(duì)照上圖,一步一步對(duì) singleton 類型 bean 的生命周期進(jìn)行解析:

實(shí)例化 bean 對(duì)象,類似于 new XXObject()

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

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

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

檢查 bean 對(duì)象是否實(shí)現(xiàn)了 InitializingBean 接口,如果實(shí)現(xiàn),則調(diào)用 afterPropertiesSet 方法。或者檢查配置文件中是否配置了 init-method 屬性,如果配置了,則去調(diào)用 init-method 屬性配置的方法。

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

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

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

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

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

圖2 依賴實(shí)例化流程圖

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

圖3 循環(huán)依賴

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

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

public interface BeanPostProcessor {

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

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

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

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

檢查 Pointcut 中的表達(dá)式是否能匹配當(dāng)前 bean 對(duì)象。

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

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

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

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

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

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

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

參考

《Spring揭秘》

《Spring源碼深度解析》

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

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


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

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/70177.html

相關(guān)文章

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

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

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

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

    xorpay 評(píng)論0 收藏0
  • Learn Spring - Spring IoC

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

    luzhuqun 評(píng)論0 收藏0
  • Spring知識(shí)——IOC容器

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

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

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

    Cciradih 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

趙連江

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<