Spring Boot @Condition 註解,組合條件你知道嗎

上一篇文章 你應該知道的 @ConfigurationProperties 註解的使用姿式,這一篇就夠了 介紹瞭如何經過 @ConfigurationProperties 註解靈活讀取配置屬性,這篇文章將介紹如何靈活配置 Spring Beanjava

寫在前面

當咱們構建一個 Spring 應用的時候,有時咱們想在知足指定條件的時候纔將某個 bean 加載到應用上下文中, 在Spring 4.0 時代,咱們能夠經過 @Conditional 註解來實現這類操做 git

咱們看到 @Conditional 註解接收的參數是 extends Condition 接口的泛型類,也就是說,咱們要使用 @Conditional 註解,只須要實現 Condition 接口並重寫其方法便可: github

看到接口的 matches 方法返回的是 boolean 類型,是否是和咱們自定義 validation annotation 有些相似,都是用來判斷是否知足指定條件。另外注意看,以上註解和接口都在 org.springframework.context.annotation package 中web

終於到了 Spring Boot 時代,在這個全新的時代,Spring Boot 在 @Conditional 註解的基礎上進行了細化,無需出示複雜的介紹信 (實現 Condition 接口),只須要手持預約義好的 @ConditionalOnXxxx 註解印章的門票,若是驗證經過,就會走進 Application Context 大廳面試

註解詳解

Spring Boot 對 @Conditional 註解爲咱們作了細化,這些註解都定義在 org.springframework.boot.autoconfigure.condition package 下 spring

逐個打開這 13 個註解,咱們發現這些註解上有相同的元註解: 多線程

從這些標記上咱們能夠了解以下內容:app

  • 均可以應用在 TYPE 上,也就是說,Spring 自動掃描的一切類 (@Configuration, @Component, @Service, @Repository, or @Controller) 均可以經過添加相應的 @ConditionalOnXxxx 來判斷是否加載框架

  • 均可以應用在 METHOD 上,因此有 @Bean 標記的方法也能夠應用這些註解spring-boot

  • 都是用了 @Conditional 註解來標記,OnBeanCondition 等自定義 Condition 仍是實現了 Condition 接口的,換湯不換藥,沒什麼神祕的,只不過作了更具象的封裝罷了,來看類依賴圖:

其實看這些註解字面意思已經能理解這些註解的含義,可是咱們仍是要說明具體的使用以及一些注意事項,我按照我的使用頻次由高到低講解:

@ConditionalOnProperty

毫無疑問這個註解是榜首

這個條件解釋是: application.properties 或 application.yml 文件中 mybean.enable 爲 true 纔會加載 MyCondition 這個 Bean,若是沒有匹配上也會加載,由於 matchIfMissing = true,默認值是 false。

@ConditionalOnBean 和 ConditionalOnMissingBean

有時候咱們須要某個 Bean 已經存在應用上下文時纔會加載,那麼咱們會用到 @ConditionalOnBean 註解:

與之相反,有時候咱們須要某個 Bean 不存在於應用上下文時纔會加載,那麼咱們會用到 @ConditionalOnMissingBean 註解

@ConditionalOnClass 和 @ConditionalOnMissingClass

不要嫌我廢話,和上面的同樣,只不過判斷某個類是否存在於 classpath 中,這就不作過多說明了

@ConditionalOnExpression

若是咱們有更復雜的多個配置屬性一塊兒判斷,那麼咱們就能夠用這個表達式了:

只有當兩個屬性都爲 true 的時候才加載 MyModule,到這裏要順便揭曉上一篇文章 你應該知道的 @ConfigurationProperties 註解的使用姿式,這一篇就夠了 靈魂追問 3,其中 :true 就是: 若是沒有爲該屬性設置值,則爲該屬性設置默認值true, 其實這就是@Vaue 註解的規範,一切 SpEL 均可以應用在這裏.

寫到這,我經常使用的已經用完了,還要硬着頭皮介紹其餘幾個內容 😄,開個玩笑,我們繼續:

@ConditionalOnSingleCandidate

這個註解和 @ConditionalOnBean 相似,爲了更好的說明該註解的使用 (實際上是 才疏學淺 ) ,我只能翻譯一下類的註釋了

只有指定類已存在於 BeanFactory 中,而且能夠肯定單個候選項纔會匹配成功

BeanFactory 存在多個 bean 實例,可是有一個 primary 候選項被指定(一般在類上使用 @Primary 註解),也會匹配成功。實質上,若是自動鏈接具備定義類型的 bean 匹配就會成功

目前,條件只是匹配已經被應用上下文處理的 bean 定義,自己來說,強烈建議僅僅在 auto-configuration 類中使用這個條件,若是候選 bean 被另一個 auto-configuration 建立,確保使用該條件的要在其後面運行

@ConditionalOnResource

若是咱們要加載的 bean 依賴指定資源是否存在於 classpath 中,那麼咱們就可使用這個註解

看到這個 logback.xml 是否是很親切,在咱們引入第三方工具類如 Dozer 等均可以添加相似的開關

接下來的是真冷門,你們有個印象,若是有須要,至少能想到用這些註解實現靈活配置就行了

@ConditionalOnJndi

只有指定的資源經過 JNDI 加載後才加載 bean

@ConditionalOnJava

只有運行指定版本的 Java 纔會加載 Bean

@ConditionalOnWebApplication 和 @ConditionalOnNotWebApplication

只有運行在 web 應用裏纔會加載這個 bean

與之相反,在非 web 環境才加載 bean

@ConditionalOnCloudPlatform

這個註解冷的我呼吸都要中止了,只有運行在指定的雲平臺上才加載指定的 bean,CloudPlatform 是 org.springframework.boot.cloud 下一個 enum 類型的類,你們能夠打開自行看看:

到此,Spring Boot 爲咱們提供的這 13 個註解就介紹完了,可是沒有結束,下面的一些冷門知識,你須要知道:

組合條件

組合條件 AND

若是咱們想多個條件一塊兒應用,而且條件的關係是 and,咱們只須要在類上使用多個@ConditionalOnXxxx 就能夠了 (你這也叫冷門?) ,固然也能夠繼承 AllNestedConditions類封裝咱們多個條件

這樣就有了組合 and 條件,只有內部全部條件都知足,才加載指定 bean

組合條件 OR

若是咱們但願組合的條件是 or 的關係,咱們該怎麼辦呢? 咱們能夠經過繼承 AnyNestedCondition 來完成這一要求,示例代碼和上面同樣,你們自行打開 AnyNestedCondition 類,查看類說明便可

條件組合 NONE

有 and 和 or 就確定有 non(非),咱們能夠經過繼承 NoneNestedConditions 完成這一要求,你們自行查看便可

自定義註解

經過組合方式實現了多條件邏輯應用,咱們須要應用這些組合條件也就要自定義註解,其實文章開頭已經講過了,模仿內置的 13 個註解寫就行了:

只須要經過@Conditional註解指定咱們自定義的 condition 類就行了,而後應用到你想用的地方就行了

仍是推薦你們看 RabbitMq 的 RabbitAutoConfiguration 類,這個類裏面主流的註解都是用了 (只看這一個類就行了),你們看框架理解學習這些註解是更好的方式:

github.com/spring-proj…

總結

到這裏,你已經瞭解瞭如何靈活配置 bean,結合以前的文章,相信的定義會更加靈活,但願你們打開 IDE,自行查看這些註解,瞭解更多具體內容

靈魂追問

  1. SpringBoot 添加了 web starter,有哪些方法將其更改成非 web 應用?
  2. Java8 Stream 也有 findAny,findAll 這類的操做,這都是匹配,你有使用過嗎?
  3. 看下面這段代碼,若是 classpath 中沒有 MyBean class,編譯會報錯,那這個註解什麼用呢?
@Configuration    
@ConditionalOnClass(MyBean.class)
public class MyConfiguration{
    // omitted       
}
```## 提升效率工具

![](http://rgyb.sunluomeng.top/%E5%85%AC%E4%BC%97%E8%B4%A6%E5%8F%B7%E6%96%87%E7%AB%A0/%E6%84%9F%E6%83%B3%E4%B8%8E%E6%80%BB%E7%BB%93/_image/2019-06-18/b.png) 

--------

## 推薦閱讀
+ [紅黑樹,超強動靜圖詳解,簡單易懂](https://mp.weixin.qq.com/s/ilND8u_8HGSTSrJiMB4X8g)
+ [雙親委派模型:大廠高頻面試題,輕鬆搞定](https://mp.weixin.qq.com/s/Dnr1jLebvBUHnziZzSfcrA)
+ [面試還不知道BeanFactory和ApplicationContext的區別?](https://mp.weixin.qq.com/s/YBQB086ADBjHUmwrFQrWew)
+ [如何設計好的RESTful API](https://mp.weixin.qq.com/s/hR1TqkVzwZ_T8fuMnsM4hQ)
+ [程序猿爲何要看源碼?](https://mp.weixin.qq.com/s/V7h8O6pVFQ-nr_iA2SNqtw)

--------
> ### 歡迎持續關注公衆號:「日拱一兵」
> - 前沿 Java 技術乾貨分享 
> - 高效工具彙總 
> - 面試問題分析與解答 
> - 技術資料領取
**後續會推出 「多線程」以及「ElasticSearch」等連載內容**
> 以讀偵探小說思惟輕鬆趣味學習 Java 技術棧相關知識,本着將複雜問題簡單化,抽象問題具體化和圖形化原則逐步分解技術問題,技術持續更新,請持續關注......

![](http://rgyb.sunluomeng.top/%E5%85%AC%E4%BC%97%E8%B4%A6%E5%8F%B7%E6%96%87%E7%AB%A0/%E6%84%9F%E6%83%B3%E4%B8%8E%E6%80%BB%E7%BB%93/_image/2019-06-18/a%20%281%29.png)複製代碼
相關文章
相關標籤/搜索