Spring Boot 自動配置一篇概覽

一、什麼是自動配置 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 條件

@ConditionalOnBean、ConditionalOnMissingBean 
@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 {};
}
search 屬性用於限定搜尋範圍。
作用於 @Bean 註解的方法時,默認的目標 Bean 類型爲方法的返回值類型。如下:
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、資源條件

@ConditionalOnResource 基於是否存在特定的資源來判正,如:判定資源“file:/home/user/test.dat”。

5、Web 應用條件

@ConditionalOnWebApplication、@ConditionalOnNotWebApplication
基於當前是否爲 Web 應用。
@ConditionalOnWarDeployment、@ConditionalOnNotWarDeployment 判定當前應用是否爲傳統的部署到 servlet 容器的 WAR 包應用,區別於內嵌的 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 模塊

提供依賴。顯示聲明所有必需的依賴,對於可選的,不要聲明。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章