一個Spring Bean從誕生到逝去的九次人生轉折!

有道無術,術尚可求也!有術無道,止於術!

關於Spring生命週期的學習,前面已經寫過不少篇文章去不斷的探究Spring對一個Bean的建立、管理過程,在整個SpringBean的生命週期中,BeanPostProcessor是不可繞過的一環,他幾乎貫穿了整個Spring Bean的生命週期!幾乎咱們如今所熟知Bean的生命週期的功能,大部分都是由BeanPostProcessor完成的!好比,依賴注入、循環依賴問題、Aop等,所有都是由BeanPostProcessor的擴展實現的!java

BeanPostProcessor的學習是咱們理解Spring如何插手對象實例化的一個重要的轉折點!咱們經過BeanPostProcessor的擴展,可以對Spring作一些很'騷'的操做!web

以往的每一篇文章,對於SpringBean生命週期的介紹,都是從程序掃描開始的,可是事實上,既然是一個Bean的聲明週期,那麼對於生命週期的理解就要從對象的初始化開始!本篇文章將從頭至尾解析Spring BeanPostProcessor整個回調實現!spring

1、尋找合適的構造函數建立對象

java建立對象是基於反射來建立的!反射建立對象也是基於構造函數來建立的!Spring也不可能脫離於java以外,因此spring在建立對象以前必需要作的就是,他要肯定本次建立對象,所須要的構造函數!設計模式

爲何須要推斷構造函數呢?由於Spring在幫咱們管理bean的時候它並不知道他要使用什麼樣的構造方法!由於咱們都知道Spring給咱們提供的屬性注入裏面有一個【構造函數注入】!假設你有兩個構造函數,此時Spring就會很混亂,他也不知道應該使用哪種!因此Spring在建立對象以前會使用一個擴展點,去推斷出符合Spring條件的構造函數,而後再下面建立對象的時候,選擇一個最爲合適的構造函數建立對象!緩存

image-20200930083709224

推斷構造函數的回調就是經過SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors方法來作的!SmartInstantiationAwareBeanPostProcessor是BeanPostProcessor裏面的一個子類,它對原有的接口進行增長,增長determineCandidateConstructors方法,再建立對象以前會回調這個方法,推斷出將來建立對象的時候可能要須要的構造方法!事實上!這裏也會進行註解@Lookup的解析,後面的學習也會說到,這裏不重點說!微信

image-20200929183514382

Spring默認的實現是: AutowiredAnnotationBeanPostProcessorapp

它是默認尋找加了@Autowired註解的構造方法,這裏就不細說了,後面會有專門的篇章來介紹Spring的構造方法推斷!編輯器

咱們本身也能夠基於這個擴展點去擴展Spring,使得Spring建立對象前擁有更多的可能性!函數

擴展點:實現AutowiredAnnotationBeanPostProcessor接口複寫determineCandidateConstructors方法來控制準備使用的構造函數!post

2、解析你的各種Spring註解

java在建立對象完成後,理所應當就是應該去開始向對象注入屬性,可是有一點,在注入屬性的時候就必需要知道一件事,就是那個屬性須要注入!

因此Spring爲了方便起見,在注入屬性以前我就把你對象裏面將來要操做的屬性給解析了,而後保存起來,將來進行對象屬性注入或其餘操做的時候就不須要在進行解析了,直接從緩存中取,也從側面體現了設計模式中職責單一的特色!

image-20200930085029741

對於@Autowired,@Value的解析是由BeanPostProcessor的子類MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition來作的!

在建立完成對象以後,填充對象以前會 進行這一步操做,Spring內置了一個AutowiredAnnotationBeanPostProcessor的實現,他的主要做用是用於解析註解@Value、@Autowired等註解,將對應的屬性或者方法和其對應的註解屬性包裝成一個對象,緩存起來,以便於在填充屬性的時候,直接進行從緩存獲取進行屬性的填充!

擴展點:實現MergedBeanDefinitionPostProcessor接口複寫postProcessMergedBeanDefinition方法來控制一些特殊註解的解析!

3、循環依賴中三級緩存的精髓

屬性和方法解析完成以後,此時就應該開始注入屬性了,在注入屬性以前須要保存一個工廠對象,基於這個工廠對象可以返回一個bean對象!爲何要保存工廠對象呢?還記得Spring爲了解決循環依賴中的代理問題,就建立了一個三級緩存,裏面主要存放爲了生成代理對象的工廠對象,這第三次回調就是這個代理對象生成器!

上期Spring三級緩存的問題說的很明白,這裏爲何會放一個工廠,這裏不作太多的贅述!可是,工廠對象裏面是如何生成一個代理對象呢?

他是基於SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference的方法來解決代理邏輯的!假設對象發生了循環依賴,就會經過工廠調用這個方法,最終完成AOP的邏輯!

image-20200930091453985

須要注意的是,這裏僅僅是設置了一個代理邏輯,並無真正的調用,這個在整個Spring解決循環依賴中說的很明白!他的調用時機是在被依賴的時候,這裏不作贅述!

4、你的自動注入生不生效我說的算

在對象初始化以後,屬性注入以前,會進行一次屬性是被可以被注入的回調,該回調會返回一個布爾類型的返回值來驗證最終屬性是否生效!

該方法最終會回調InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation方法,該方法的定義以下:

image-20200930092524103

擴展點:實現InstantiationAwareBeanPostProcessor接口複寫postProcessAfterInstantiation方法來控制這個類到底需不須要自動注入!

5、屬性填充

屬性填充是基於後置處理器來作的,這裏會會尋找(二)中尋找到的@Value或@Autowirte等屬性或者方法,進行對應數據的注入!

Spring自動注入屬性的時候會回調,InstantiationAwareBeanPostProcessor#postProcessProperties回調,完成最後的屬性注入!所注入的標識就是在第二步尋找到的字段和方法,經過反射進行操做!

image-20200930120942897

經過實現InstantiationAwareBeanPostProcessor重寫postProcessProperties方法,能夠在某個對象屬性注入的時候,就行值得修改操做,能夠插手Spring對於值的注入的問題!

和全部的都同樣,都是尋找到全部的值,進行循環調用!最後返回屬性與值的對應關係以供後續使用!

image-20200930122250525

擴展點:實現InstantiationAwareBeanPostProcessor接口複寫postProcessProperties方法來控制這個類即將要注入的屬性或方法的值!

6、花式Aware接口調用

不知道你是否使用過Spring提供的一些Aware這些額外的擴展接口,不瞭解的能夠去了解一下,靈活使用Aware接口,能夠爲Spring增長不少意想不到不到的功能,好比一些SpringUtil固然大部分是這樣命名的,就是經過Aware接口來實現的!

image-20200930123958962

擴展點:實現以上三個接口複寫對應的方法能夠獲取對應的屬性!

7、Spring Bean初始化前,你想幹什麼?

你想在Spring調用你的初始化方法以前作些什麼嗎?Spring固然爲你提供了修改的可能性!

Spring在bean初始化前會回調【BeanPostProcessor#postProcessBeforeInitialization】方法!

image-20200930130522577

擴展點:實現BeanPostProcessor複寫postProcessBeforeInitialization方法能夠在類初始化以前進行修改bean!

8、你想在Bean被完全建立完成前作些什麼嗎?

Spring在這一步會回調你的初始化方法,也就是實現了InitializingBean接口的afterPropertiesSet方法

image-20200930134022751

擴展點:實現InitializingBean複寫afterPropertiesSet()方法可讓bean在初始化的時候作些什麼!

9、Spring Bean完成初始化後,你想作些什麼?

Spring完成了整個Bean的生命週期了,你想在這個時候作些什麼嗎?還記得Spring Aop嗎?他就是在這一步進行完成的!

image-20200930141228497

這一步的調用是Spring生命週期的最後一步,咱們所熟知的AOP 也是在這裏進行裝載完成的!

擴展點:實現BeanPostProcessor複寫postProcessAfterInitialization()方法能夠修改bean的最終返回實例!

最後,祝你們雙節快樂!另外,國慶期間做者就不更新了!我要出去浪一段時間,哈哈!而後做者是個窮屌絲,沒錢發紅包!告辭!

10、總結


BeanPostProcessor

才疏學淺,若是文章中理解有誤,歡迎大佬們私聊指正!歡迎關注做者的公衆號,一塊兒進步,一塊兒學習!



       
❤️「轉發」 「在看」 ,是對我最大的支持❤️



本文分享自微信公衆號 - JAVA程序狗(javacxg)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索