Spring源碼解析后置處理器梳理總結(jié)
前言
在前面幾篇文章中梳理了Spring中bean的創(chuàng)建過程,在這個(gè)過程中各式各樣的后置處理器發(fā)揮了不同的作用,可以說后置處理器貫穿了bean的實(shí)例化以及初始化過程。在這篇文章中,將按照出場(chǎng)順序?qū)笾锰幚砥髯饔脠?chǎng)景及發(fā)揮功能進(jìn)行梳理。
1、InstantiationAwareBeanPostProcessor的postProcessBeforeInstantiation()方法
AbstractAutowireCapableBeanFactory
的createBean
方法中調(diào)用,這時(shí)bean還沒有被實(shí)例化:
調(diào)用resolveBeforeInstantiation
方法:
applyBeanPostProcessorsBeforeInstantiation
方法:
在這里,首先拿到spring中提供的所有后置處理器,判斷是不是InstantiationAwareBeanPostProcessor
。該后置處理器實(shí)現(xiàn)了BeanPostProcessor
,在這調(diào)用了postProcessBeforeInstantiation
方法。
這里在目標(biāo)對(duì)象被spring實(shí)例化之前調(diào)用,postProcessBeforeInstantiation
方法的返回值類型是Object
,可以返回任何類型的值。由于此時(shí)目標(biāo)對(duì)象還未實(shí)例化,所以這個(gè)返回值可以用來代替原本該生成的目標(biāo)對(duì)象的實(shí)例,一般為代理對(duì)象。
如果該方法的返回的Object
對(duì)象代替了原本該生成的目標(biāo)對(duì)象,那么就會(huì)把返回的對(duì)象放到單例池當(dāng)中緩存,后續(xù)只有BeanPostProcessor
的postProcessAfterInitialization
方法會(huì)調(diào)用,其它方法不再調(diào)用。
如果這里返回了null
,就按照正常的流程創(chuàng)建對(duì)象,交給spring去負(fù)責(zé)對(duì)象的實(shí)例化。因此這個(gè)方法可以判斷這個(gè)對(duì)象在spring實(shí)例化之前是否要做特殊的處理,比如不交給Spring管理,自己使用代理產(chǎn)生。
2、SmartInstantiationAwareBeanPostProcessor的determineCandidateConstructors()方法
在AbstractAutowireCapableBeanFactory
的createBeanInstance
方法中調(diào)用:
determineConstructorsFromBeanPostProcessors
方法,該方法用于推斷實(shí)例化的構(gòu)造方法,這里可能檢測(cè)出bean擁有多個(gè)候選構(gòu)造方法:
SmartInstantiationAwareBeanPostProcessor
接口的實(shí)現(xiàn)類AutowiredAnnotationBeanPostProcessor
負(fù)責(zé)完成這個(gè)過程,如果有多個(gè)構(gòu)造方法的情況下,ctors
會(huì)返回空,后續(xù)使用默認(rèn)無參構(gòu)造方法進(jìn)行實(shí)例化。但是如果有一個(gè)構(gòu)造方法上有@Autowired
注解,spring會(huì)優(yōu)先選擇這個(gè)方法。
3、MergedBeanDefinitionPostProcessor的postProcessMergedBeanDefinition()方法
AbstractAutowireCapableBeanFactory
的doCreateBean
方法中調(diào)用:
applyMergedBeanDefinitionPostProcessors
方法:
在方法中對(duì)所有實(shí)現(xiàn)了MergedBeanDefinitionPostProcessor
接口的后置處理器進(jìn)行遍歷,這里具體調(diào)用AutowiredAnnotationBeanPostProcessor
,用于掃描需要注入的屬性。
AutowiredAnnotationBeanPostProcessor
中,定義了兩種需要掃描的注解類型,@Autowired
和@Value
在findAutowiredAnnotation
方法中:
對(duì)正在創(chuàng)建的bean進(jìn)行掃描,如果有屬性和方法上面加了這兩個(gè)注解,就會(huì)把對(duì)應(yīng)的方法或者屬性保存,最終在buildAutowiringMetadata
方法中封裝成InjectionMetadata
對(duì)象。
需要注意這里的后置處理器僅僅用于掃描及緩存bean的注入信息,這里只完成了查找功能,沒有完成屬性的注入,屬性的注入是在之后的另外的后置處理器中完成的。
4、SmartInstantiationAwareBeanPostProcessor的getEarlyBeanReference()方法
在AbstractAutowireCapableBeanFactory
的doCreateBean
方法中調(diào)用,主要用于處理Bean的循環(huán)依賴:
在產(chǎn)生循環(huán)依賴后調(diào)用getEarlyBeanReference
方法:
在這里遍歷后置處理器,得到經(jīng)過后置處理器代理后的對(duì)象,放入spring的二級(jí)緩存當(dāng)中,提前暴露供循環(huán)引用的情況調(diào)用。注意這里返回的僅僅是一個(gè)對(duì)象,還算不上是一個(gè)完整的bean對(duì)象。這個(gè)具體調(diào)用過程在上一篇講循環(huán)依賴的中的文章中講的比較詳細(xì),如果有不明白的可以回顧一下。
5、InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation()方法
在AbstractAutowireCapableBeanFactory
的populateBean
方法中調(diào)用:
在populateBean
方法中:
該方法在目標(biāo)對(duì)象實(shí)例化之后調(diào)用,這個(gè)時(shí)候?qū)ο笠呀?jīng)被實(shí)例化,但是該實(shí)例的屬性還未被設(shè)置,都是null
。
這里遍歷后置處理器,如果實(shí)現(xiàn)了InstantiationAwareBeanPostProcessor
,那么就調(diào)用postProcessAfterInstantiation
方法。如果方法返回值為true
,按照正常流程進(jìn)行屬性值的填充;如果該方法返回false
,會(huì)忽略屬性值的設(shè)置過程。簡(jiǎn)而言之,該后置處理器用于判斷當(dāng)前實(shí)例化完成的bean需不需要進(jìn)行屬性填充。
6、InstantiationAwareBeanPostProcessor的postProcessPropertyValues()方法
同樣在populateBean
方法中,在postProcessAfterInstantiation
后返回true
時(shí)執(zhí)行,如果方法返回false
,該方法不會(huì)被調(diào)用。
遍歷后置處理器,如果屬于InstantiationAwareBeanPostProcessor
類型,則調(diào)用它的postProcessPropertyValues
方法。
這里發(fā)揮作用的是AutowiredAnnotationBeanPostProcessor
,負(fù)責(zé)對(duì)添加了 @Autowired
和@Value
等注解的屬性進(jìn)行依賴的填充。在其中遍歷所有需要注入的屬性的列表,使用反射將注入的bean實(shí)例賦值給屬性。(具體過程參照Spring實(shí)例化Bean源碼解析)
7、BeanPostProcessor的postProcessBeforeInitialization()方法
AbstractAutowireCapableBeanFactory的doCreateBean
方法中調(diào)用initializeBeanfan
方法:
applyBeanPostProcessorsBeforeInitialization
方法中:
在該方法中,遍歷執(zhí)行所有BeanPostProcessor
的postProcessBeforeInitialization
方法。
在執(zhí)行該方法前,bean已經(jīng)被實(shí)例化完成,并且完成了屬性的填充,因此這個(gè)過程屬于后續(xù)的bean的初始化過程。
需要注意的是,如果在bean中有方法被標(biāo)注了@PostContrust
注解,那么在CommonAnnotationBeanPostProcessor
中,會(huì)調(diào)用該@PostContrust
方法。
8、BeanPostProcessor的postProcessAfterInitialization()方法
和第7次調(diào)用入口相同,也是在AbstractAutowireCapableBeanFactory
的initializeBean
方法中:
applyBeanPostProcessorsAfterInitialization
方法中:
遍歷執(zhí)行所有BeanPostProcessor
的postProcessAfterInitialization
方法。綜上所述,bean的各種方法執(zhí)行屬性為,先執(zhí)行構(gòu)造方法,再執(zhí)行后置管理器中的before
方法及@PostContrust
方法,最后執(zhí)行后置處理器的after
方法。
9、InitDestroyAnnotationBeanPostProcessor的postProcessBeforeDestruction()方法
如果當(dāng)前bean中有方法被@PreDestroy
注解標(biāo)注,那么當(dāng)Spring的ApplicationContext
執(zhí)行close
方法時(shí)調(diào)用該后置處理器。在DefaultSingletonBeanRegistry
中執(zhí)行destroyBean
方法:
調(diào)用destroy
方法:
InitDestroyAnnotationBeanPostProcessor
的postProcessBeforeDestruction
方法:
在該方法中,調(diào)用@PreDestroy
注解標(biāo)注的方法,執(zhí)行銷毀方法。
總結(jié)
本文對(duì)貫穿bean的實(shí)例化及初始化過程中出現(xiàn)的后置處理器進(jìn)行了一下梳理,但是還有很多其他的后置處理器沒有講到。可以說后置處理器是spring提供給使用者的一些擴(kuò)展點(diǎn),如果能夠熟練的使用這些后置處理器,能夠幫助我們接觸到一些spring中比較深層的東西,并對(duì)spring中的生命周期進(jìn)行有利的插手。
相關(guān)文章
java 字符串轉(zhuǎn)化為字符數(shù)組的3種實(shí)現(xiàn)案例
這篇文章主要介紹了java 字符串轉(zhuǎn)化為字符數(shù)組的3種實(shí)現(xiàn)案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-10-10關(guān)于IDEA中spring-cloud-starter-alibaba-nacos-discovery 無法引入問題
這篇文章主要介紹了關(guān)于IDEA中spring-cloud-starter-alibaba-nacos-discovery 無法引入問題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-02-02SpringBoot項(xiàng)目中建議關(guān)閉Open-EntityManager-in-view原因
這篇文章主要為大家解析了在Spring Boot項(xiàng)目中建議關(guān)閉Open-EntityManager-in-view的原因示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助2022-02-02Java實(shí)現(xiàn)Twitter的分布式自增ID算法snowflake
這篇文章主要介紹了Java實(shí)現(xiàn)Twitter的分布式自增ID算法snowflake,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08