有道無術,術尚可求也!有術無道,止於術!
關於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條件的構造函數,而後再下面建立對象的時候,選擇一個最爲合適的構造函數建立對象!緩存
![](http://static.javashuo.com/static/loading.gif)
推斷構造函數的回調就是經過SmartInstantiationAwareBeanPostProcessor#determineCandidateConstructors
方法來作的!SmartInstantiationAwareBeanPostProcessor是BeanPostProcessor裏面的一個子類,它對原有的接口進行增長,增長determineCandidateConstructors方法,再建立對象以前會回調這個方法,推斷出將來建立對象的時候可能要須要的構造方法!事實上!這裏也會進行註解@Lookup
的解析,後面的學習也會說到,這裏不重點說!微信
![](http://static.javashuo.com/static/loading.gif)
Spring默認的實現是: AutowiredAnnotationBeanPostProcessor
app
它是默認尋找加了@Autowired
註解的構造方法,這裏就不細說了,後面會有專門的篇章來介紹Spring的構造方法推斷!編輯器
咱們本身也能夠基於這個擴展點去擴展Spring,使得Spring建立對象前擁有更多的可能性!函數
擴展點:實現AutowiredAnnotationBeanPostProcessor
接口複寫determineCandidateConstructors
方法來控制準備使用的構造函數!post
2、解析你的各種Spring註解
java在建立對象完成後,理所應當就是應該去開始向對象注入屬性,可是有一點,在注入屬性的時候就必需要知道一件事,就是那個屬性須要注入!
因此Spring爲了方便起見,在注入屬性以前我就把你對象裏面將來要操做的屬性給解析了,而後保存起來,將來進行對象屬性注入或其餘操做的時候就不須要在進行解析了,直接從緩存中取,也從側面體現了設計模式中職責單一的特色!
![](http://static.javashuo.com/static/loading.gif)
對於@Autowired
,@Value
的解析是由BeanPostProcessor
的子類MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition
來作的!
在建立完成對象以後,填充對象以前會 進行這一步操做,Spring內置了一個AutowiredAnnotationBeanPostProcessor
的實現,他的主要做用是用於解析註解@Value、@Autowired
等註解,將對應的屬性或者方法和其對應的註解屬性包裝成一個對象,緩存起來,以便於在填充屬性的時候,直接進行從緩存獲取進行屬性的填充!
擴展點:實現MergedBeanDefinitionPostProcessor
接口複寫postProcessMergedBeanDefinition
方法來控制一些特殊註解的解析!
3、循環依賴中三級緩存的精髓
屬性和方法解析完成以後,此時就應該開始注入屬性了,在注入屬性以前須要保存一個工廠對象,基於這個工廠對象可以返回一個bean對象!爲何要保存工廠對象呢?還記得Spring爲了解決循環依賴中的代理問題,就建立了一個三級緩存,裏面主要存放爲了生成代理對象的工廠對象,這第三次回調就是這個代理對象生成器!
上期Spring三級緩存的問題說的很明白,這裏爲何會放一個工廠,這裏不作太多的贅述!可是,工廠對象裏面是如何生成一個代理對象呢?
他是基於SmartInstantiationAwareBeanPostProcessor#getEarlyBeanReference
的方法來解決代理邏輯的!假設對象發生了循環依賴,就會經過工廠調用這個方法,最終完成AOP的邏輯!
![](http://static.javashuo.com/static/loading.gif)
須要注意的是,這裏僅僅是設置了一個代理邏輯,並無真正的調用,這個在整個Spring解決循環依賴中說的很明白!他的調用時機是在被依賴的時候,這裏不作贅述!
4、你的自動注入生不生效我說的算
在對象初始化以後,屬性注入以前,會進行一次屬性是被可以被注入的回調,該回調會返回一個布爾類型的返回值來驗證最終屬性是否生效!
該方法最終會回調InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation
方法,該方法的定義以下:
![](http://static.javashuo.com/static/loading.gif)
擴展點:實現InstantiationAwareBeanPostProcessor
接口複寫postProcessAfterInstantiation
方法來控制這個類到底需不須要自動注入!
5、屬性填充
屬性填充是基於後置處理器來作的,這裏會會尋找(二)中尋找到的@Value或@Autowirte等屬性或者方法,進行對應數據的注入!
Spring自動注入屬性的時候會回調,InstantiationAwareBeanPostProcessor#postProcessProperties
回調,完成最後的屬性注入!所注入的標識就是在第二步尋找到的字段和方法,經過反射進行操做!
![](http://static.javashuo.com/static/loading.gif)
經過實現InstantiationAwareBeanPostProcessor
重寫postProcessProperties
方法,能夠在某個對象屬性注入的時候,就行值得修改操做,能夠插手Spring對於值的注入的問題!
和全部的都同樣,都是尋找到全部的值,進行循環調用!最後返回屬性與值的對應關係以供後續使用!
![](http://static.javashuo.com/static/loading.gif)
擴展點:實現InstantiationAwareBeanPostProcessor
接口複寫postProcessProperties
方法來控制這個類即將要注入的屬性或方法的值!
6、花式Aware接口調用
不知道你是否使用過Spring提供的一些Aware這些額外的擴展接口,不瞭解的能夠去了解一下,靈活使用Aware接口,能夠爲Spring增長不少意想不到不到的功能,好比一些
SpringUtil
固然大部分是這樣命名的,就是經過Aware接口來實現的!
![](http://static.javashuo.com/static/loading.gif)
擴展點:實現以上三個接口
複寫對應的方法
能夠獲取對應的屬性!
7、Spring Bean初始化前,你想幹什麼?
你想在Spring調用你的初始化方法以前作些什麼嗎?Spring固然爲你提供了修改的可能性!
Spring在bean初始化前會回調【BeanPostProcessor#postProcessBeforeInitialization】方法!
![](http://static.javashuo.com/static/loading.gif)
擴展點:實現BeanPostProcessor
複寫postProcessBeforeInitialization
方法能夠在類初始化以前進行修改bean!
8、你想在Bean被完全建立完成前作些什麼嗎?
Spring在這一步會回調你的初始化方法,也就是實現了
InitializingBean
接口的afterPropertiesSet
方法
![](http://static.javashuo.com/static/loading.gif)
擴展點:實現InitializingBean
複寫afterPropertiesSet()方法
可讓bean在初始化的時候作些什麼!
9、Spring Bean完成初始化後,你想作些什麼?
Spring完成了整個Bean的生命週期了,你想在這個時候作些什麼嗎?還記得Spring Aop嗎?他就是在這一步進行完成的!
![](http://static.javashuo.com/static/loading.gif)
這一步的調用是Spring生命週期的最後一步,咱們所熟知的AOP 也是在這裏進行裝載完成的!
擴展點:實現BeanPostProcessor
複寫postProcessAfterInitialization()方法
能夠修改bean的最終返回實例!
最後,祝你們雙節快樂!另外,國慶期間做者就不更新了!我要出去浪一段時間,哈哈!而後做者是個窮屌絲,沒錢發紅包!告辭!
10、總結
才疏學淺,若是文章中理解有誤,歡迎大佬們私聊指正!歡迎關注做者的公衆號,一塊兒進步,一塊兒學習!
❤️「轉發」 和 「在看」 ,是對我最大的支持❤️
本文分享自微信公衆號 - JAVA程序狗(javacxg)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。