發現了Spring boot中有個注解@ConditionalOnProperty,這個注解能夠控制某個configuration是否生效。具體操作是通過其兩個屬性name以及havingValue來實現的,其中name用來從application.properties中讀取某個屬性值,如果該值為空,則返回false;如果值不為空,則將該值與havingValue指定的值進行比較,如果一樣則返回true;否則返回false。如果返回值為false,則該configuration不生效;為true則生效。
也可以在 @Service 注解一起使用. 這樣service層就可以不生效
//在application.properties配置"mf.assert",對應的值為true
@Configuration
//如果synchronize在配置文件中并且值為true
@ConditionalOnProperty(prefix="mf",name = "assert", havingValue = "true")
public class SecondDatasourceConfig {
@Bean(name = "SecondDataSource")
@Qualifier("SecondDataSource")
@ConfigurationProperties(prefix = "spring.second.datasource")
public DataSource jwcDataSource() {
return DataSourceBuilder.create().build();
}
}
一些復雜應用
最近在寫一個“啟動時導入數據”的小功能。實現很簡單, CommandLineRunner會在SpringBoot啟動時運行,第一版長這樣:
Order(1)
@Component
public class DictionaryInitializer implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
//do import dictionary
}
}
自然的,我們希望這個可配置化,只在需要的時候運行。我們使用@ConditionalOnProperty
@Order(1)
@Component
@ConditionalOnProperty(name="app.initialize.dictionary", havingValue="true")
public class DictionaryInitializer implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
//do import dictionary
}
}
然后在application.properties中加入
app.initialize.dictionary=true
隨著功能的迭代,我們又更多類似的導入功能,例如導入Product和Parameter。依樣畫葫蘆,application.properties中多了相似的配置
這個有點麻煩,涉及到多個條件的組合。ConditionalOnProperty是支持 “多個條件邏輯與”的
還有一種比較靈活的方式是使用@ConditionalOnExpression寫一個表達式
@Order(1)
@Component
@ConditionalOnExpression("${app.initialize.dictionary:false} || ${app.initialize.all:false}")
public class DictionaryInitializer implements CommandLineRunner{}
精益無止境,其實還有更靈活的配置方式:除了dictionary其他都導入:
app.initialize.all=true
app.initialize.dictionary=false
換種說法就是:如果局部有配置,則按局部配置處理。如果局部沒配置,則按全局配置處理。如果全局、局部都沒配置,則默認不導入。這里可以利用“默認值”嵌套表達式實現
@ConditionalOnExpression("${app.initialize.dictionary:${app.initialize.all:false}}")