Spring @Autowired 原理


主題

學習分享記錄一下Spring是怎么注入@Autowired標注的bean的.

 

配置BeanPostProcessor

傳統的spring項目中配置基本是通過XML來操作的.在XML中經常會有這種配置

<context:annotation-config/> 或者 <context:component-scan>

或者類似的配置.這些配置是開啟@Autowired等注解的關鍵. 先看看他們做了什么.

 

解析標簽

XML中這些特殊的namespace基本都是由XXXNameSpaceHandler來做解析的

 

比如AOPNamspaceHandler負責解析 <aop:aspectj-autoproxy /> 等命名空間

類似的context:XXX這種命名空間基本是由ContextNamespaceHandler來做處理.

 

他會解析一大堆標簽,其中我們主要要研究的額就是component-scan和annotation-config...功能有一部分重疊.

ComponentScanBeanDefinitionParser的parse方法會調用org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object) 這個方法

 

 

 

 

 

 看方法內部不難看出它往registry(BeanFactory)中添加了很多特殊的BeanPostProcessor (或者其子類).我們比較關心的是AutowiredAnnotationBeanPostProcessor

 

 

 

BeanPostProcessor

BPP這些特殊的bean會參與Spring的生命周期.

這個類最重要的地方在於impl了InstantiationAwareBeanPostProcessor和MergedBeanDefinitionPostProcessor了.

 

 

其中有3個方法的覆蓋比較關鍵.

第一個是MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition

這個時間點大致是在BeanFactory准備根據beanDifinition去創建bean的時候.會回調這個方法.

AutowiredAnnotationBeanPostProcessor在這一步驟中取查找bean有標記了@Autowired的field,method等InjectionMetadata.InjectedElement的實現..

具體的業務邏輯就不想詳細說明了.基本就是通過反射去查找要注入的元素,然后封裝到元信息里保存下來.

 

 

 


第二個是InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation返回為true.(常規的bean都會返回true)

InstantiationAwareBeanPostProcessor可以通過這個false參數來阻止屬性的注入.

當然正常情況下這里一般方式(比如XML中注入屬性)也是允許的,所以這里返回true.這就意味着bean定義和bean的部分屬性可以定義在XML中走一般的屬性注入.

而這個bean的部分屬性加上@Autowired,通過注解注入也是可以的..只是可能很少會有人這么做.

當然,設置為false的話@Autowired也不能注入.因為有短路原則.滿足這種情況的話只有BeanPostProcessor.postProcessAfterInitialization會被調用.

 

第三個方法是InstantiationAwareBeanPostProcessor.postProcessPropertyValues

這個回調函數發生的時間是在BeanFactory去populateBean的時候.也就是說bean已經new了.正在初始化他的屬性,且通過正常方式(比如XML里定義的屬性)已經完成的時候.

 

 通過獲取之前第一步中記錄下來的metaData.InjectedElement.對於每一個element去掉inject方法.

 

 method和field因為是2種實現類.所以方法實現會有一點點區別.但是大致還是一樣的...可以來看看field的.

最核心的也就是.問BF去取bean.

我有一個field.我有一個需要的type.你BF找到bean給我..就這樣.

https://www.cnblogs.com/binarylei/p/12337145.html

可以參考上面這篇文章怎么從BF中取bean.

絕大部分情況下基本就是從BeanDifination中取出類型匹配的bean的name.然后再去找對應的bean.

找到了bean以后就通過field.set去設置一下即可.

 

小結

1.Spring中這么多騷操作離不開BeanPostProcessor等特殊的bean.在XML對應的applicationContext的時候通過NamspaceHandler解析XML節點,並去注冊AutowiredAnnotationBeanPostProcessor等bean.

2.AutowiredAnnotationBeanPostProcessor

通過MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition在doCreateBean當前bean的時候收集當前的需要@Auwotired的element的元數據信息

通過InstantiationAwareBeanPostProcessor.postProcessPropertyValues在populateBean的時候,即設置當前bean的屬性的時候獲取之前的需要注入的elment.然后去BF中獲取對應的bean.並set.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM