一、什麼是自動配置 bean
自動配置類通過添加 @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
1、關於約定:
自動配置類必須通過如上配置文件引入。
合理規劃其放置包位置,避免被自動包掃描。
內部不要配置自動包掃描,如需要可以使用 @Import 引入。
2、關於順序
明確的對象先後順序可以通過配置 @AutoConfiguration 的 before、beforeName、after、afterName 屬性,或者使用 @AutoConfigurationBefore、@AutoConfigurationAfter 註解實現。例如 web 服務類配置需要置於 @WebMvcAutoConfiguration 註解之後。
如果沒有明確的先後順序,也可以使用 @AutoConfigureOrder 註解聲明順序。類似 @ Order 註解,不同之處在於其只作用於自動配置類。
三、條件註解
1、類條件
@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(); } } }
2、Bean 條件
@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 類型判定的條件註解時尤爲重要。
3、屬性條件
@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; }
可以基於前綴或者特定名稱來判斷。
4、資源條件
5、Web 應用條件
四、構建 starter
一個典型的 Spring Boot starter 包括如下兩點:
-
autoconfigure
模塊:包含自動配置相關代碼。 -
starter
模塊:提供 autoconfigure 模塊所需的依賴及其它附屬依賴。
1、命名
不要以 spring-boot 做前綴,這是官方保留使用。
以自有工程名做前綴,並附加信息體現其用途。
2、配置鍵
配置鍵需要提供專門的命名空間,不要使用 Spring Boot 官方命名空間,
3、autoconfigure 模塊
包含使用依賴的所有配置,也可以包括配置鍵定義及自定義組件初始化的回調接口。
所有引入應該做成可配置的,並且默認爲不使用。
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>
4、starter 模塊
提供依賴。顯示聲明所有必需的依賴,對於可選的,不要聲明。