Spring Boot — 自動配置原理

  • 2020 年 2 月 10 日
  • 筆記

啟用自動配置

在Spring Boot中自動配置一般使用@EnableXXX方式,Spring默認提供了@EnableAutoConfiguration來配置starter,另外還提供了類似@EnableScheduling來配置非starter的相關bean,從源碼角度來看,兩種方式本質上來說並沒什麼區別,其都使用了@Import來導入一個對應的配置入口類,然後正在啟動中的Spring IoC容器會嘗試初始化該類,那麼該配置入口類相當於拿到了ApplicationContext,自然可以做很多的自由發揮。

清單1:EnableAutoConfiguration源碼

@Target(ElementType.TYPE)  @Retention(RetentionPolicy.RUNTIME)  @Documented  @Inherited  @AutoConfigurationPackage  @Import(EnableAutoConfigurationImportSelector.class)  public @interface EnableAutoConfiguration {    	String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";      // .......  }

清單2:EnableScheduling源碼

@Target(ElementType.TYPE)  @Retention(RetentionPolicy.RUNTIME)  @Import(SchedulingConfiguration.class)  @Documented  public @interface EnableScheduling {    }

如何自動配置

所謂的自動配置就是執行具體的Configuration類,首先先看比較簡單的@EnableScheduling註解,該註解對應的配置類為SchedulingConfiguration,在SchedulingConfiguration中往IOC中注入了一個DestructionAwareBeanPostProcessor處理器,用於掃描定時器方法,然後初始化整個定時器調度。 這個簡單的自動配置也說明了@EnableXXX本質上是一個開關,告訴Spring該去配置哪些東西,該怎麼配置這些東西。 清單3:EnableScheduling對應的SchedulingConfiguration配置

@Configuration  @Role(BeanDefinition.ROLE_INFRASTRUCTURE)  public class SchedulingConfiguration {    	@Bean(name = TaskManagementConfigUtils.SCHEDULED_ANNOTATION_PROCESSOR_BEAN_NAME)  	@Role(BeanDefinition.ROLE_INFRASTRUCTURE)  	public ScheduledAnnotationBeanPostProcessor scheduledAnnotationProcessor() {  		return new ScheduledAnnotationBeanPostProcessor();  	}  }

那麼對於starter模組是如何做到自動配置的呢?答案是@EnableAutoConfiguration,該註解對應的配置類為EnableAutoConfigurationImportSelector,該類實現了ImportSelector介面,在Spring Boot的Application Context啟動時會主動調用其org.springframework.context.annotation.ImportSelector#selectImports方法,那麼自動注入的核心就在該方法中。

EnableAutoConfigurationImportSelector在啟動後回去掃描META-INF/spring.factories文件,該文件是Spring Boot提供的Starter自我配置的入口,以mybatis starter為例,其形式如下: 清單4: mybatis starter配置

# Auto Configure  org.springframework.boot.autoconfigure.EnableAutoConfiguration=  org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration

其目地告訴Spring Boot使用org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration來配置我這個模組,Spring Boot獲取到該配置後會經過一系列的判斷(比如是否被用戶手動exclude),然後決定載入後將該類納入Spring Boot的配置中去,讓IoC容器去完成配置。到此整個自動配置發現流程就算完成,這種方式類似Java提供的SPI,利用classpath下的配置資訊達到批量自動配置的目地。

如何利用自動配置

自動配置的原理是很簡單的,總結起來就兩種,如果你想要讓用戶主動配置,那麼可以提供一個自定義的EnableXXX註解,在該註解中import對應的配置類,如果你想讓Spring Boot再啟動的時候自動配置,那麼在META-INF下提供對應的spring.factories文件,讓Spring自動載入對應的配置類。

Spring Boot利用這種做法能讓模組與模組之間解耦,所有的模組之間通過IoC容器進行聯繫,那麼對寫程式碼就很有啟發了,比如在項目中要對接多個簡訊服務商,那麼每一個簡訊服務商實際上就是一個Plugin,那麼給每一個服務商寫一個EnableXXX註解,讓Spring自動配置到IoC容器中,使用方也只需要從IoC中獲取,也是一種不錯的解耦的設計。

參考

Creating Your Own Auto-configuration