Spring Boot核心原理-自動配置 以及@ConfigurationProperties 註解

      若是你所在的公司要開發一個共享的lib,或者若是你想要爲開源世界作點貢獻,你也許想要開發你本身的自定義的自動配置類以及你本身的starter pom。這些自動配置類雖然在一個單獨的jar包中,但卻依然可以被Spring Boot獲取到。web

自動配置(Auto-configuration)其實就是一個starter。starter這個詞是否是很熟悉,沒錯,就是Spring Boot中的那些看起來略屌的啓動器。如今你能夠本身編寫一個本身的starter了。在一個starter裏,你能夠把一組dependency和標記有@Configuration的類放在這個starter裏。spring

1.理解 auto-configured beans

自動配置使用標準的@Configuration類實現。 而後能夠搭配@Conditional註解來規定在什麼條件下這些配置會被使用和生效。 其中自動配置類最經常使用到的就是@ConditionalOnClass和@ConditionalOnMissingBean這兩個註解。 express

這樣的話,就能夠保證在找到相關的類或Bean的時候的時候自動配置類纔會生效。session

2.如何定位自動配置類

若是你在本身單獨的jar包中編寫了一個自動配置類,並且加上了@Configuration以及其它約束條件,這時候引入依賴的話,你的Configuration並不會生效。app

你還須要在你的starter項目中的resources文件夾下加上META-INF /spring.factories這樣的目錄和文件,Spring Boot會檢查你發佈的jar中是否存在META-INF / spring.factories文件。 在這個文件中你應該把你的配置類加入進來,像下面這樣,在一個EnableAutoConfiguration key下。spring-boot

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.mycorp.libx.autoconfigure.LibXAutoConfiguration,\
com.mycorp.libx.autoconfigure.LibXWebAutoConfiguration

若是你的配置類須要按照必定的順序來逐個生效的話,你可使用@AutoConfigureAfter或@AutoConfigureBefore來實現。spa

好比,若是你搞了個web的一個自定義配置,那麼你的這個配置的生效就要排在WebMvcAutoConfiguration的後面設計

蕾絲下面這樣:code

 

@Configuration
@AutoConfigureAfter(WebMvcAutoConfiguration.class)
public class HornetQAutoConfiguration {...

若是您想排序某些彼此不該該有什麼直接關聯的自動配置類的話,您還可使用@AutoconfigureOrder。 該註解與常規的@Order註解具備相同的語義,但爲自動配置類提供了一個你想要的順序。排序

/**
 * Auto-configuration爲你定義了好幾個註解可讓你的自動配置類按照必定的順序自動排列
* 具體就是經過AnnotationConfigApplicationContext#register(Class...)}來爲你生成的

 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD })
public @interface AutoConfigureOrder {
    /**
     * 排序方式. 默認是Ordered#LOWEST_PRECEDENCE
     * @see Ordered#getOrder()
     * @return the order value
     */
    int value() default Ordered.LOWEST_PRECEDENCE;
}

這個Ordered也就是兩種狀況:

public interface Ordered {
    int HIGHEST_PRECEDENCE = -2147483648;//優先級最高
    int LOWEST_PRECEDENCE = 2147483647;//優先級最低
    int getOrder();
}

NOTE:自動配置類只能以這種方式加載。這樣才能保證他們被限定在特定包中而且它們不會被其它的組件掃描到!

3. Condition註解

通常狀況下,你都要給你的自動配置類加上一個或者更多的@Conditional註解。好比@ConditionalOnMissingBean就是一個比較常見的例子,當你容許開發人員去覆蓋自動配置的時候,那麼強烈建議你使用這個註解,這樣的話,若是開發人員以爲你的自動配置並不能知足需求,那麼他能夠自定義。

特別注意:@ConditionalOnMissingBean也只適合在自動配置類中使用。千萬不要亂用。

Spring Boot自帶了一些@Conditional註解,你能夠在你的代碼中重用,在標記了@Configuration的類或@Bean方法上。

3.1 Class conditions

@ConditionalOnClass和@ConditionalOnMissingClass註解其實就是當特定的類存在就生效,反之亦然。 因爲這些註解上的元數據是使用ASM來解析,因此你能夠經過name屬性來引入一個類,這樣也不在意這個類在沒在你的classpath中。

@ConditionalOnClass(name ="de.MyService")

若是你使用value屬性的話,若是所在類不存在的話,則會報錯致使編譯沒法經過。

像下面這樣:

@ConditionalOnClass({de.MyService.class})

3.2 Bean conditions

@ConditionalOnBean和@ConditionalOnMissingBean上面已經介紹過了。也能夠經過name或value屬性來指定bean。 還有一個search屬性,經過該屬性你能夠指定搜索bean時所使用的ApplicationContext。


3.3 Property conditions


@ConditionalOnProperty註解容許配置包含基於Spring Environment的屬性。 使用prefix和name屬性指定應檢查的屬性。 默認狀況下,任何存在且不等於false的屬性都將匹配。 你還可使用havingValue和matchIfMissing屬性進行更高級的過濾和檢查。

@ConditionalOnProperty(prefix = "hornetq.embedded", value = "enabled", havingValue ="true", matchIfMissing = true)

static class EmbeddedServerConfiguration {

//相似這樣,hrnetq.embedded.enabled=true,EmbeddedServerConfiguration的配置就生效了;

//若是你把havingValue修改成false,該配置仍是生效的,由於你加了matchIfMissing = true,若是你把

//matchIfMissing改成false,該配置就失效了。

3.4 Resource conditions

@ConditionalOnResource 同理,當某個資源文件存在時,則配置生效。 

資源可使用一般的Spring約定來指定,例如,file:/home/user/test.dat。

3.5 Web application conditions

同理@ConditionalOnWebApplication 和 @ConditionalOnNotWebApplication是用來判斷應用是否是web應用:web application。

 

這裏所說的Web應用程序是指任何使用了Spring WebApplicationContext,定義了session scope或者有標準servlet環境的任何應用程序。

3.6 SpEL expression conditions

@ConditionalOnExpression也是同樣的。至於SpEL是個什麼東東?這裏不贅述了。

 

相似這樣的用法:

@ConditionalOnExpression("'Hello World'.concat('!')")

源碼:

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnExpressionCondition.class)
public @interface ConditionalOnExpression {

    /**
     * 設置spring的表達式語言: SpEL expression。表達式應該返回true或false。默認是true
     * @return the SpEL expression
     */
    String value() default "true";

}

4 建立你本身的starter

一個完整的Spring Boot 的starter能夠包含兩個組件(注意:是「能夠」包含):

  • autoconfigure 模塊。 自動配置類代碼。

  • starter 模塊。 自動配置相關的依賴以及其它要啓動starter所要提供能力的相關依賴,總之,要保證starter所提供的能力可以正常啓動。

     

NOTE:若是你以爲不必把這兩個分開的話,你能夠把兩個模塊合併成一個。

 

 

4.1 起名字

不說了。學會模仿。

4.2 Autoconfigure 模塊

Autoconfigure模塊包含有你的自動配置類以及和配置類相關聯的類好比@ConfigurationProperties這些類以及任何未來要進一步自定義組件的回調接口等代碼。

NOTE:注意把一些庫的dependency標記爲optional,以便您能夠更輕鬆地在項目中包含自動配置模塊。這也是你設計sdk的一些技巧。

4.3 Starter 模塊

Starter模塊就是一個空的jar。裏邊只有一個pom。而後提供啓動所須要的依賴。

-----------分割線--------------

:你須要加入兩個與自動配置相關的依賴:

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-autoconfigure</artifactId>
</dependency>

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-configuration-processor</artifactId>
   <optional>true</optional>
</dependency>

-----------我再分-----------

相關文章
相關標籤/搜索