Spring ConfigurationClassPostProcessor Bean解析及自注冊過程
v一、Bean的自注冊過程
v二、自注冊過程說明
vConfigurationClassParser解析流程
1、處理@PropertySources註解,配置資訊的解析
2、處理@ComponentScan註解:使用ComponentScanAnnotationParser掃描basePackage下的需要解析的類(@SpringBootApplication註解也包括了@ComponentScan註解,只不過basePackages是空的,空的話會去獲取當前@Configuration修飾的類所在的包[這個會在下面詳細解釋]),並註冊到BeanFactory中(這個時候bean並沒有進行例項化,而是進行了註冊。具體的例項化在finishBeanFactoryInitialization方法中執行)。對於掃描出來的類,遞迴解析
3、處理@Import註解:先遞迴找出所有的註解,然後再過濾出只有@Import註解的類,得到@Import註解的值。比如查詢@SpringBootApplication註解的@Import註解資料的話,首先發現@SpringBootApplication不是一個@Import註解,然後遞迴呼叫修飾了@SpringBootApplication的註解,發現有個@EnableAutoConfiguration註解,再次遞迴發現被@Import(EnableAutoConfigurationImportSelector.class)修飾,還有@AutoConfigurationPackage註解修飾,再次遞迴@AutoConfigurationPackage註解,發現被@Import(AutoConfigurationPackages.Registrar.class)註解修飾,所以@SpringBootApplication註解對應的@Import註解有2個,分別是@Import(AutoConfigurationPackages.Registrar.class)和@Import(EnableAutoConfigurationImportSelector.class)。找出所有的@Import註解之後,開始處理邏輯:
(1)、遍歷這些@Import註解內部的屬性類集合
(2)、如果這個類是個ImportSelector介面的實現類,例項化這個ImportSelector,如果這個類也是DeferredImportSelector介面的實現類,那麼加入ConfigurationClassParser的deferredImportSelectors屬性中讓第6步處理。否則呼叫ImportSelector的selectImports方法得到需要Import的類,然後對這些類遞迴做@Import註解的處理
(3)、如果這個類是ImportBeanDefinitionRegistrar介面的實現類,設定到配置類ConfigurationClass的importBeanDefinitionRegistrars屬性中
(4)、其它情況下把這個類入隊到ConfigurationClassParser的importStack(佇列)屬性中,然後把這個類當成是@Configuration註解修飾的類遞迴重頭開始解析這個類
4、處理@ImportResource註解:獲取@ImportResource註解的locations屬性,得到資原始檔的地址資訊。然後遍歷這些資原始檔並把它們新增到配置類的importedResources屬性中
5、處理@Bean註解:獲取被@Bean註解修飾的方法,然後新增到配置類的beanMethods屬性中
6、處理DeferredImportSelector:處理第3步@Import註解產生的DeferredImportSelector,進行selectImports方法的呼叫找出需要import的類,然後再呼叫第3步相同的處理邏輯處理
v@SpringBootApplication註解
@SpringBootApplication註解被@EnableAutoConfiguration修飾,@EnableAutoConfiguration註解被@Import(EnableAutoConfigurationImportSelector.class)修飾,所以在第3步會找出這個@Import修飾的類EnableAutoConfigurationImportSelector,這個類剛好實現了DeferredImportSelector介面,接著就會在第6步被執行。第6步selectImport得到的類就是自動化配置類。
EnableAutoConfigurationImportSelector的selectImport方法會在spring.factories檔案中找出key為EnableAutoConfiguration對應的值【這些值就是所謂的自動化配置類(XXXAutoConfiguration)】。
ConfigurationClassParser解析完成之後,被解析出來的類會放到configurationClasses屬性中。然後使用ConfigurationClassBeanDefinitionReader去解析這些類。
vComponentScanAnnotationParser包掃描相關
首先啟動一個springboot web工程,找到ApplicationContext的父類org.springframework.context.support.AbstractApplicationContext
我們發現,其真實的物件的型別是AnnotationConfigEmbeddedWebApplicationContext。 自身構造過程如下。
繼續追蹤AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry)
終於找到了ConfigurationClassPostProcessor自注冊後置處理器。這裡有個有趣的ConfigurationClassPostProcessor解析流程, 內部呼叫中會使用 ComponentScanAnnotationParser去掃描,ComponentScanAnnotationParser類的parse方法有這樣一段邏輯
if (basePackages.isEmpty()) { basePackages.add(ClassUtils.getPackageName(declaringClass)); }
參考下面的相關圖:
也就是如果basePackages沒有配置,會找declaringClass 對應包及其子包,declaringClass對應springboot專案中我們寫的Application.java(@SpringBootApplication)
v呼叫棧
v實際專案結構
包結構這樣的話,即使不配置componentScan,不使用AutoConfiguration,也可以掃描到bean。Application.java帶有@SpringbootApplication註解,該註解中帶有@ComponentScan註解,Application.java包的範圍包含了所有java檔案,所以專案中所有bean都可以被掃描到。
注:declaringClass 指的是帶有@ComponentScan 註解的類
相關文章
- Spring Bean 的例項化過程原始碼解析SpringBean原始碼
- Spring建立Bean的過程DebugSpringBean
- Spring原始碼解析之ConfigurationClassPostProcessor(三)Spring原始碼
- Spring原始碼解析之ConfigurationClassPostProcessor(一)Spring原始碼
- Spring原始碼解析之ConfigurationClassPostProcessor(二)Spring原始碼
- Spring 原始碼(10)Spring Bean 的建立過程(1)Spring原始碼Bean
- Spring 原始碼(11)Spring Bean 的建立過程(2)Spring原始碼Bean
- Spring 原始碼(12)Spring Bean 的建立過程(3)Spring原始碼Bean
- Spring 原始碼(13)Spring Bean 的建立過程(4)Spring原始碼Bean
- Spring 原始碼(14)Spring Bean 的建立過程(5)Spring原始碼Bean
- Spring 原始碼(17)Spring Bean的建立過程(8)Bean的初始化Spring原始碼Bean
- 淺嘗Spring註解開發_Bean生命週期及執行過程SpringBean
- Spring中Bean及@Bean的理解SpringBean
- spring通過註解註冊bean的方式+spring生命週期SpringBean
- DNS解析全過程及原理DNS
- Spring Bean 標籤解析SpringBean
- 死磕Spring之IoC篇 - Bean 的建立過程SpringBean
- Spring BeanFactory例項化Bean的詳細過程SpringBean
- Spring系列(一):Spring MVC bean 解析、註冊、例項化流程原始碼剖析SpringMVCBean原始碼
- Spring 原始碼(9)Spring Bean的建立過程的前期準備Spring原始碼Bean
- Spring 原始碼(16)Spring Bean的建立過程(7)屬性填充Spring原始碼Bean
- Spring原始碼分析之Bean的建立過程詳解Spring原始碼Bean
- 【Spring原始碼分析】原型Bean例項化過程、byName與byType及FactoryBean獲取Bean原始碼實現Spring原始碼原型Bean
- go dns解析過程及調優GoDNS
- 【Spring】BeanFactory 解析 bean 詳解SpringBean
- Spring 原始碼(14)Spring Bean 的建立過程(6)物件的提前暴露Spring原始碼Bean物件
- spring註冊bean的幾種方式SpringBean
- Spring Ioc原始碼分析系列--Bean例項化過程(二)Spring原始碼Bean
- Spring Ioc原始碼分析系列--Bean例項化過程(一)Spring原始碼Bean
- 誰能告訴我spring中bean的裝載過程,SpringBean
- Spring IoC Context啟動過程解析SpringContext
- Spring原始碼解析-applicationContext.xml載入和bean的註冊Spring原始碼APPContextXMLBean
- 我該如何學習spring原始碼以及解析bean定義的註冊Spring原始碼Bean
- IoC-spring 的靈魂(帶你輕鬆理解IOC思想及bean物件的生成過程)SpringBean物件
- 【spring原始碼學習】spring的IOC容器在初始化bean過程Spring原始碼Bean
- Spring通過factory配置beanSpringBean
- Spring 原始碼學習 - 單例bean的例項化過程Spring原始碼單例Bean
- Spring原始碼淺析之bean例項的建立過程(一)Spring原始碼Bean