裝配 SpringBoot自動配置流程

源碼分析SpringBoot自動配置流程?
? 首先,我們要了解在@SpringBootApplication注解的內部,還具有@EnableAutoConfiguration,@SpringBootConfiguration,@ComponentScan三個主要注解 。
@SpringBootConfiguration//標注該類是配置類 , 需要通過該類查找自動配置文件@EnableAutoConfiguration //自動配置的關鍵注解 其內部就是執行自動配置的代碼@ComponentScan(excludeFilters = {//type : 要使用的篩選器類型,classes 指定類型篩選器//TypeExcludeFilter.class 篩選掉spirngBootApplication中被指定排除的配置類@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),//AutoConfigurationExcludeFilter 將配置類與spirng.factories中的EnableAutoConfiguration對應的配置類進行對比匹配 ,  如果一致,會被排除掉 @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) } ) //掃描指定包的文件,將帶有特定注解的類注入到Bean中public @interface SpringBootApplication {}@ComponentScan

  1. @ComponentScan注解主要用來掃描我們項目中的所有被像@service ,@Repository , @Controller , @configuration 等注解修飾的類,將其注入到我們的IOC容器中,其中也包括我們的自動配置的文件:
@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)@Documented@Repeatable(ComponentScans.class)//表示可以重復利用@ComponentScan注解/** *作用 : 可以掃描指定的包 , 如果未指定包范圍,將從該注解標注類所在的包進行掃描,*與XML形式的<context:component scan>不同的是 @componentScan沒有Config屬性(true* 就開啟了屬性自動注入的功能,如果是false就是關閉屬性自動注入的功能),因為使用 *@ComponentScan則默認所有的類都進行自動注入,會將所有掃描到的組件注入到IOC容器中 */public @interface ComponentScan {}@SpringBootConfiguration
  1. @SpringBootConfiguration 是SpringBoot替代@Configuration的注解,增加了自動找到配置的功能
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Configuration//表示這是一個配置類 通過其間接了解到 , @SpringBootApplication也是一個配置類/*** 用作Spring的標準@Configuration注解的替代,以便可以自動找到配置*/public @interface SpringBootConfiguration {}@EnableAutoConfiguration
  1. @EnableAutoConfiguration注解就是啟動自動配置的關鍵注解,其內部使用了@import注解引入了一個AutoConfigurationImportSelector 自動配置類選擇器
@AutoConfigurationPackage //自動配置所在包注解,通過basePackages指定配置所在的包或者通過basePackageClasses指定基本包類,如果未指定,會默認注冊指定注解類所在的包//AutoConfigurationImportSelector自動配置選擇器,實現了ImportSelector接口,重寫了selectImports方法,自動配置的具體實現就在其內部進行//ImportSelector接口作用 :根據給定的選擇條件(通常是一個或多個注解屬性)確定應導入哪個配置類 。@Import(AutoConfigurationImportSelector.class)public @interface EnableAutoConfiguration {}? 在其內部重寫了selectImports方法,通過調用getAutoConfigurationEntry()方法根據傳入的注解元數據,獲取到自動配置類的實體 , 而后從實體中獲取具體的配置信息,配置信息在實體內部是一個list集合,所以將其轉化為String數組后返回 。
//為方便顯示及理解,省略了該類實現的部分接口和具體的代碼實現,需要了解可進入源碼查看public class AutoConfigurationImportSelector implements DeferredImportSelector {@Override public String[] selectImports(AnnotationMetadata annotationMetadata) { //AnnotationMetadata: 配置類的注解元數據,也就是配置類的注解信息//調用getAutoConfigurationEntry()方法根據傳入的注解信息,獲取并返回自動配置類的實體AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);//從配置實體中獲取具體的配置信息,返回的是一個list集合,而后通過toStringArray()方法轉存到字符串數組中返回return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations()); }}getAutoConfigurationEntry()//可以先看下獲取的大致流程,而后進入查看器方法內部的具體實現protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {//1.從注解元數據中獲取注解的相應屬性,將相應屬性存儲到map中返回//1.1AnnotationAttributes是一個Map集合,其繼承了LinkedHashMapAnnotationAttributes attributes = getAttributes(annotationMetadata);//2. 通過getCandidateConfigurations()方法根據注解元數據和注解的屬性信息 獲取應該進行自動配置的類名,可以理解為自動配置候選項List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);//2.1 通過removeDuplicates()方法對自動配置的類名進行去重處理configurations = removeDuplicates(configurations);//3. 根據注解元數據和注解屬性獲取到需排除配置項Set<String> exclusions = getExclusions(annotationMetadata, attributes);//3.1檢查是否有無效的排除類存在checkExcludedClasses(configurations, exclusions);//3.2從自動配置候選項中刪除需要排除的配置項configurations.removeAll(exclusions);//4. 調用getConfigurationClassFilter()方法獲取到獲取配置的所有AutoConfigurationImportFilter的實現類(對spring.factories進行過濾的類),調用filter方法對配置文件進行篩?。?而后返回需要自動配置的類configurations = getConfigurationClassFilter().filter(configurations);//5. 根據spring.factories文件中的AutoConfigurationImportListener事件監聽器發布并處理監聽事件,最后根據多次過濾、判重返回配置類合集fireAutoConfigurationImportEvents(configurations, exclusions);//6. 創建一個新的配置實體ConfigurationEntry并返回,包含需要配置項configurations,和被排除配置項exclusionsreturn new AutoConfigurationEntry(configurations, exclusions); }

推薦閱讀