自動設定類通過新增 @AutoConfiguration 註解實現。
因為 @AutoConfiguration 註解本身是以 @Configuration 註解的,所以自動設定類可以算是一個標準的基於 @Configuration 註解的類。
@Conditional 註解可以用於宣告自動設定啟用條件,通常,我們可以使用 @ConditionalOnClass、@ConditionalOnMissingBean 註解。
Spring Boot 通過檢查【META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports】組態檔獲取自動設定類。
檔案內包含自定義的自動設定類全限定名,每行一個。
範例如下:
com.mycorp.libx.autoconfigure.LibXAutoConfiguration com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration
自動設定類必須通過如上組態檔引入。
合理規劃其放置包位置,避免被自動包掃描。
內部不要設定自動包掃描,如需要可以使用 @Import 引入。
明確的物件先後順序可以通過設定 @AutoConfiguration 的 before、beforeName、after、afterName 屬性,或者使用 @AutoConfigurationBefore、@AutoConfigurationAfter 註解實現。例如 web 服務類設定需要置於 @WebMvcAutoConfiguration 註解之後。
如果沒有明確的先後順序,也可以使用 @AutoConfigureOrder 註解宣告順序。類似 @ Order 註解,不同之處在於其只作用於自動設定類。
@ConditionalOnClass、@ConditionalOnMissingClass
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Conditional({OnClassCondition.class}) public @interface ConditionalOnClass { Class<?>[] value() default {}; String[] name() default {}; }
註解後設資料是通過 ASM 處理的,所以可以通過 value 屬性傳遞 Class 型別引數,或者也可以通過 name 傳遞類全限定名作為引數。
無效情景:
@Bean 註解的方法,其返回值型別為類目標條件類本身。在方法上的條件判正之前,JVM 已經載入了相關的類,並且很可能會執行相關的方法參照,如果類不存在的話,就會導致失敗。
為了處理此類情景,需要新增額外的 @Configuration 註解,使用如下:
import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @AutoConfiguration // Some conditions ... public class MyAutoConfiguration { // Auto-configured beans ... @Configuration(proxyBeanMethods = false) // @ConditionalOnClass(SomeService.class) public static class SomeServiceConfiguration { @Bean @ConditionalOnMissingBean public SomeService someService() { return new SomeService(); } } }
@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Documented @Conditional({OnBeanCondition.class}) public @interface ConditionalOnBean { Class<?>[] value() default {}; String[] type() default {}; Class<? extends Annotation>[] annotation() default {}; String[] name() default {}; SearchStrategy search() default SearchStrategy.ALL; Class<?>[] parameterizedContainer() default {}; }
import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; @AutoConfiguration public class MyAutoConfiguration { @Bean @ConditionalOnMissingBean public SomeService someService() { return new SomeService(); } }
條件註解的判正會受 Bean 定義的註冊、處理順序影響,這點需要特別關注。通常建議只在自動設定類上使用條件註解。
@ConditionalOnBean、ConditionalOnMissingBean 條件註解的 @Configuration 類依然會被建立,只不是不會被註冊。
當使用 @Bean 註解方法時,返回值最好使用具體的類,而不要使用介面。這一點,對於使用基於 Bean 型別判定的條件註解時尤為重要。
@ConditionalOnProperty 基於 Spring 的環境變數判正。
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) @Documented @Conditional({OnPropertyCondition.class}) public @interface ConditionalOnProperty { String[] value() default {}; String prefix() default ""; String[] name() default {}; String havingValue() default ""; boolean matchIfMissing() default false; }
可以基於字首或者特定名稱來判斷。
一個典型的 Spring Boot starter 包括如下兩點:
autoconfigure
模組:包含自動設定相關程式碼。
starter
模組:提供 autoconfigure 模組所需的依賴及其它附屬依賴。
不要以 spring-boot 做字首,這是官方保留使用。
以自有工程名做字首,並附加資訊體現其用途。
設定鍵需要提供專門的名稱空間,不要使用 Spring Boot 官方名稱空間,
包含使用依賴的所有設定,也可以包括設定鍵定義及自定義元件初始化的回撥介面。
所有引入應該做成可設定的,並且預設為不使用。
Spring Boot 使用註解處理器來收集位於組態檔(META-INF/spring-autoconfigure-metadata.properties)中的自動設定條件,快速過濾掉不需要自動設定的,以加快啟動速度。
如果使用 Maven 管理專案,則需要加入如下依賴來處理啟用自動設定功能:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-autoconfigure-processor</artifactId> <optional>true</optional> </dependency>
提供依賴。顯示宣告所有必需的依賴,對於可選的,不要宣告。