文章目錄
一、前言
本文,是本人在閱讀源碼過程中的一些內容整理和總結。
全文僅代表個人理解和意見,故難免出現錯誤,如若發現,歡迎指正。十分謝謝。
本文所涉及的文章內容均在 : Spring源碼分析:全集整理
關於 :ConfigurationClassPostProcessor
和 AutowiredAnnotationBeanPostProcessor
的詳細分析,可以在 Spring源碼分析:全集整理 中找到對應的分析文章。
二、正文
2.1 Spring IOC 實現個人感覺最重要的兩個類
-
ConfigurationClassPostProcessor
: 完成了類的掃描和配置了的解析 -
AutowiredAnnotationBeanPostProcessor
: 完成了非 Property 的屬性的注入
-
ConfigurationClassPostProcessor
是BeanFactoryPostProcessor
子類。postProcessBeanDefinitionRegistry
: 解析所有需要註冊的配置類
postProcessBeanFactory
:對Full類型進行代理增強,保證@Bean方法正確語意。 -
AutowiredAnnotationBeanPostProcessor
是BeanPostProcessor
子類,完成了@Autowired、@Value、@Inject
註解的解析注入功能。也就是說AutowiredAnnotationBeanPostProcessor
中才完成了屬性的注入。
2.2 Spring什麼時候掃描的包路徑?
Spring在啓動時候會將啓動類註冊到Spring容器中。在ConfigurationClassPostProcessor
中,會將啓動類作爲配置類進行解析。由於啓動類上面有@ComponentScan
註解,所以在ConfigurationClassParser# doProcessConfigurationClass中
會解析這個註解, 根據解析後的路徑通過
his.componentScanParser, parse (componentScan,sourceClass.getMetadata () .getClassName())
進行掃描,註冊掃描到的需要注入的類(被@Component
修飾的類)並進行注入,如果有配置類再進行遞歸的配置類解析。(掃描是在 方法 org.springframework.context. annotation.ClassPathBeanDefinitionScanner#doScan
中進行的掃描,但是我偷懶了沒看具體實現)
2.2 ConfigurationClassPostProcessor 的解析流程
. ConfigurationClassPostProcessor
完成了對各種配置類的掃描,並將其引入的bean註冊到BeanFactory中。
-
postProcessBeanDefinitionRegistry
方法邏輯(完成了各種配置類的解析和註冊) -
獲取所有
BeanFactory
中的BeanDefinition
。 -
遍歷所有
BeanDefinition
,篩選出full或者lite 配置類,等待下一步處理。Full
規則 :被@Configuration
註解修飾 &&proxyBeanMethods
屬性爲true (默認爲true)Lite
規則:被@Component. @ComponentScan, @Import. @ImportResource
修飾的類或者類中有被@Bean修飾的方法(該方法會被包裝成一個 BeanDefinition)
-
遍歷所有full 和lite配置類,解析各種註解,對配置類進行進一步的解析(因爲Lite的配置類需要二次解析,所以這裏主要是二次解析)
- 對
@Component
進行解析:即如果當前配置類被@Component註解修飾,則去解析其內部類(包括靜態內部類和非靜態內部類)是否是配置類,如果是,遞歸解析發現的配置類。 - :對
@PropertySource
進行解析:解析出其指定的配置文件內容,並保存到environment 中 - :對
@ComponentScan
註解的解析:獲取註解指定路徑,進行掃描註冊。對新掃描出來的BeanDefinition進行判定是否是配置類,如果是,則遞歸去解析配置類 - 對
@Import、ImportSelector、ImportBeanDefinitionRegistrar
的解析:因爲這三個註解或接口,本質上完成的功能是.一樣的,都是引入類。所以在這一部分的處理上只是區分了不同的類型 - 對
@ImportResource
註解的解析:提取出@ImportResource
註解的屬性,保存到configClass
的importedResources
屬性中 - 對被
@Bean修飾的方法
的解析:提取出@Bean修飾的方法,保存的到configClass
的beanMethods
屬性中. - 對接口的默認方法解析:保存的到
configClass
的beanMethods
屬性中 - 對父類的解析:如果存在父類,則遞歸其父類進行解析。
- 對
-
遍歷所有的配置類,進行註冊
- 處理引入的配置類:將配置類信息封裝成
BeanDefinition
,並註冊到BeanFactory
- 處理
@Bean修飾的方法
:將@Bean修飾的方法封裝成BeanDefinition,並註冊到BeanFactory
中 - 處理
@ImportResource
註解引入的資源文件,獲取到BeanDefinition並註冊。 - 處理
@Import、ImportSelector、ImportBeanDefinitionRegistrar
引入的類,註冊到BeanFactory
中。
- 處理引入的配置類:將配置類信息封裝成
補充:4.1 中爲什麼要解析@Component
?
- 因爲過濾出來的配置類可能沒有被
@Component
修飾,比如僅僅是,可能是Spring硬編碼注入或者我們通過編碼注入的bean。如果沒有使用@Component
註解修飾,就沒必要解析其內部類是否是配置類。比如最簡單的就是spring.factories
文件中引入的類。可能滿足配置類判定,但並沒有被@Component
修飾
2.3 AutowiredAnnotationBeanPostProcessor 的解析流程
AutowiredAnnotationBeanPostProcessor
完成@Autowired. @Value、 @Inject
註解的功能, 完成了
Spring的注入
-
determineCandidateConstructors
方法 :篩選出當前bean中能作爲構造注入的構造函數列表。用於構造注入- 處理了
@Lookup
註解,將@Lookup
註解標註的方法保存了起來。這一步和構造函數的篩選沒有任何關係 - 挑選候選構造函數。簡單邏輯就是有註解修飾選註解修飾的構造函數,沒有的話使用默認無參構造函數沒有無參構造函數,再沒有返回null.
- 處理了
-
postProcessProperties
方法 :篩選Bean中需要注入的屬性,進行屬性注入。用於設置注入和註解注入遍歷每個屬性,找到被注入註解修飾的屬性。保存到currElements
中。遍歷每個方法,找到被注入註解修飾的方法, 保存到currElements
中。隨後遍歷currElements
, 通過resolveDependency
方法將方法或者屬性注入(resolveDependency
方法是在populateBean
方法中按照類型注入時調用的方法)這裏可以知道,按照順序遍歷,方法的屬性在屬性的後面,自動注入時,方法的注入結果會把註解屬性的注入覆蓋掉。
注: Spring注入的方式分爲三種 :構造注入、設值注入、註解注入。在AutowiredAnnotationBeanPostProcessor
中處理的實際是設置注入和註解注入。