一、處理@PropertySources註解,配置信息的解析java
二、處理@ComponentScan註解:使用ComponentScanAnnotationParser掃描basePackage下的須要解析的類(@SpringBootApplication註解也包括了@ComponentScan註解,只不過basePackages是空的,空的話會去獲取當前@Configuration修飾的類所在的包[這個會在下面詳細解釋]),並註冊到BeanFactory中(這個時候bean並無進行實例化,而是進行了註冊。具體的實例化在finishBeanFactoryInitialization方法中執行)。對於掃描出來的類,遞歸解析web
三、處理@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註解以後,開始處理邏輯:spring
(1)、遍歷這些@Import註解內部的屬性類集合springboot
(2)、若是這個類是個ImportSelector接口的實現類,實例化這個ImportSelector,若是這個類也是DeferredImportSelector接口的實現類,那麼加入ConfigurationClassParser的deferredImportSelectors屬性中讓第6步處理。不然調用ImportSelector的selectImports方法獲得須要Import的類,而後對這些類遞歸作@Import註解的處理微信
(3)、若是這個類是ImportBeanDefinitionRegistrar接口的實現類,設置到配置類ConfigurationClass的importBeanDefinitionRegistrars屬性中this
(4)、其它狀況下把這個類入隊到ConfigurationClassParser的importStack(隊列)屬性中,而後把這個類當成是@Configuration註解修飾的類遞歸重頭開始解析這個類spa
四、處理@ImportResource註解:獲取@ImportResource註解的locations屬性,獲得資源文件的地址信息。而後遍歷這些資源文件並把它們添加到配置類的importedResources屬性中code
五、處理@Bean註解:獲取被@Bean註解修飾的方法,而後添加到配置類的beanMethods屬性中component
六、處理DeferredImportSelector:處理第3步@Import註解產生的DeferredImportSelector,進行selectImports方法的調用找出須要import的類,而後再調用第3步相同的處理邏輯處理對象
@SpringBootApplication註解被@EnableAutoConfiguration修飾,@EnableAutoConfiguration註解被@Import(EnableAutoConfigurationImportSelector.class)修飾,因此在第3步會找出這個@Import修飾的類EnableAutoConfigurationImportSelector,這個類恰好實現了DeferredImportSelector接口,接着就會在第6步被執行。第6步selectImport獲得的類就是自動化配置類。
EnableAutoConfigurationImportSelector的selectImport方法會在spring.factories文件中找出key爲EnableAutoConfiguration對應的值【這些值就是所謂的自動化配置類(XXXAutoConfiguration)】。
ConfigurationClassParser解析完成以後,被解析出來的類會放到configurationClasses屬性中。而後使用ConfigurationClassBeanDefinitionReader去解析這些類。
首先啓動一個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)
包結構這樣的話,即便不配置componentScan,不使用AutoConfiguration,也能夠掃描到bean。Application.java帶有@SpringbootApplication註解,該註解中帶有@ComponentScan註解,Application.java包的範圍包含了全部java文件,因此項目中全部bean均可以被掃描到。
注:declaringClass 指的是帶有@ComponentScan 註解的類
歡迎訪問微信訂閱號原文:ConfigurationClassPostProcessor Bean解析及自注冊過程
就先分享這麼多了,更多分享請關注咱們的技術公衆吧!!!