Spring Boot中@ConditionalOnProperty使用詳解
- 2019 年 12 月 20 日
- 筆記
Spring Boot中的使用
在Spring Boot的源碼中,比如涉及到Http編碼的自動配置、數據源類型的自動配置等大量的使用到了@ConditionalOnProperty的註解。
HttpEncodingAutoConfiguration類中部分源程式碼:
@Configuration(proxyBeanMethods = false) @EnableConfigurationProperties(HttpProperties.class) @ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) @ConditionalOnClass(CharacterEncodingFilter.class) @ConditionalOnProperty(prefix = "spring.http.encoding", value = "enabled", matchIfMissing = true) public class HttpEncodingAutoConfiguration { // 省略內部程式碼 }
DataSourceConfiguration類中部分程式碼:
@Configuration(proxyBeanMethods = false) @ConditionalOnClass(org.apache.tomcat.jdbc.pool.DataSource.class) @ConditionalOnMissingBean(DataSource.class) @ConditionalOnProperty(name = "spring.datasource.type", havingValue = "org.apache.tomcat.jdbc.pool.DataSource", matchIfMissing = true) static class Tomcat { // 省略內部程式碼 }
很顯然,以上兩個自動配置類中都通過@ConditionalOnProperty來控制自動配置是否生效,下面我們來了解一下它的源碼和具體使用。
@ConditionalOnProperty源碼說明
@ConditionalOnProperty註解類源碼如下:
@Retention(RetentionPolicy.RUNTIME) @Target({ ElementType.TYPE, ElementType.METHOD }) @Documented @Conditional(OnPropertyCondition.class) public @interface ConditionalOnProperty { // 數組,獲取對應property名稱的值,與name不可同時使用 String[] value() default {}; // 配置屬性名稱的前綴,比如spring.http.encoding String prefix() default ""; // 數組,配置屬性完整名稱或部分名稱 // 可與prefix組合使用,組成完整的配置屬性名稱,與value不可同時使用 String[] name() default {}; // 可與name組合使用,比較獲取到的屬性值與havingValue給定的值是否相同,相同才載入配置 String havingValue() default ""; // 缺少該配置屬性時是否可以載入。如果為true,沒有該配置屬性時也會正常載入;反之則不會生效 boolean matchIfMissing() default false; }
其中在歷史版本中還存在一個relaxedNames屬性:
//是否可以鬆散匹配 boolean relaxedNames() default true;
最新版本中已經不存在該屬性了。
通過註解ConditionalOnProperty上的@Conditional(OnPropertyCondition.class)程式碼,可以看出ConditionalOnProperty屬於@Conditional的衍生註解。生效條件由OnPropertyCondition來進行判斷。
使用方法
關於@ConditionalOnProperty的使用方法,我們在上面的Spring Boot中的使用已經看到。
@ConditionalOnProperty的核心功能是通過屬性name以及havingValue來實現的。
首先看matchIfMissing屬性,用來指定如果配置文件中未進行對應屬性配置時的默認處理:默認情況下matchIfMissing為false,也就是說如果未進行屬性配置,則自動配置不生效。如果matchIfMissing為true,則表示如果沒有對應的屬性配置,則自動配置默認生效。
下面看name屬性,name用來從application.properties中讀取某個屬性值。比如上面Tomcat的自動配置在配置文件為:
spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource
在matchIfMissing為false時,如果name值為空,則返回false;如果name不為空,則將該值與havingValue指定的值進行比較,如果一樣則返回true,否則返回false。返回false也就意味著自動配置不會生效。
但是如果看HttpEncodingAutoConfiguration類上的屬性配置發現並沒有完全按照上面所說的name和havingValue配合使用。它是通過「prefix value」作為屬性的名稱來進行配置:
spring.http.encoding.enabled=true
其中prefix指定了配置的統一前綴「spring.http.encoding」,而value指定了具體的屬性名稱為「enabled」。這裡並沒有設置havingValue的值,如果havingValue未指定值,默認情況下在屬性配置中設置的值為true則生效(如上配置),false則不生效。