@Configuration
public class Config {
@Conditional(MyCondition.class)
@Bean
public String condition() {
System.err.println("自定義的condition的match方法返回值爲true時,纔會進入該方法創建bean");
return "";
}
/**
* 該Abc class位於類路徑上時
*/
@ConditionalOnClass(Abc.class)
@Bean
public String abc() {
System.err.println("ConditionalOnClass true");
return "";
}
// @ConditionalOnClass(Abc.class)
// @Bean
// public Abc newAbc() {
// System.err.println("ConditionalOnClass true");
// return new Abc();
// }
/**
* 存在Abc類的實例時
*/
@ConditionalOnBean(Abc.class)
@Bean
public String bean() {
System.err.println("ConditionalOnBean is exist");
return "";
}
@ConditionalOnMissingBean(Abc.class)
@Bean
public String missBean() {
System.err.println("ConditionalOnBean is missing");
return "";
}
/**
* 表達式爲true時
*/
@ConditionalOnExpression(value = "true")
@Bean
public String expresssion() {
System.err.println("expresssion is true");
return "";
}
/**
* 配置文件屬性是否爲true
*/
@ConditionalOnProperty(
value = {"abc.property"},
matchIfMissing = false)
@Bean
public String property() {
System.err.println("property is true");
return "";
}
}
這裏面有個空類Abc.class,你可以就創建個叫Abc的類,裏面是空的就行。
public class MyCondition implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
//判斷當前系統是Mac,Windows,Linux
return conditionContext.getEnvironment().getProperty("os.name").contains("Mac");
}
}
@Conditional(MyCondition.class) 這句代碼可以標註在類上面,表示該類下面的所有@Bean都會啓用配置 也可以標註在方法上面,只是對該方法啓用配置 除了自己自定義Condition之外,Spring還提供了很多Condition給我們用
@ConditionalOnBean(僅僅在當前上下文中存在某個對象時,纔會實例化一個Bean)
@ConditionalOnClass(某個class位於類路徑上,纔會實例化一個Bean)
@ConditionalOnExpression(當表達式爲true的時候,纔會實例化一個Bean)
@ConditionalOnMissingBean(僅僅在當前上下文中不存在某個對象時,纔會實例化一個Bean)
@ConditionalOnMissingClass(某個class類路徑上不存在的時候,纔會實例化一個Bean)
@ConditionalOnNotWebApplication(不是web應用)
以上是一些常用的註解,其實就是條件判斷,如果爲true了就創建Bean,爲false就不創建,就這麼簡單。
這些註解裏的條件可以是多個,也可以賦默認值,也可以標註在類上,如果標註在類上,則對類裏的所有@Bean方法都生效。
其中@ConditionalOnProperty是指在application.yml裏配置的屬性是否爲true,其他的幾個都是對class的判斷。
我在配置里加上abc.property = true這個配置就可以測試上面的代碼了。
然後再來一個對類進行多個條件標註的例子:
@Configuration
@ConditionalOnProperty(
value = {"abc.property"},
matchIfMissing = false
)
@ConditionalOnClass(Abc.class)
public class Multi {
@Bean
@ConditionalOnMissingBean({Abc.class})
public String check() {
System.err.println("multi check");
return "check";
}
}
可能上面的那些你用的地方不常見,那我來舉一個我正在使用的例子。我的應用是基於SpringCloud的,在線上部署時有eureka來做註冊中心,而在本地環境下,我的應用是單機的,不需要eureka,但是代碼裏已經引入了eureka了,每次啓動就會自動去連接eureka,然後控制檯就開始報錯。雖然不影響功能,但是看着一直不停的報錯也是不順眼。
那麼我就可以使用Condition註解來解決它。
@Component
@ConditionalOnProperty(value = "open.eureka")
@EnableDiscoveryClient
public class JudgeEnableDiscoveryClient {
}
我把EnableDiscoveryClient這個註解單獨放個類裏,裏面什麼也不寫,條件就是application.yml裏配置的open.eureka 如果我只想讓線上的環境開啓eureka,那麼我就在application-prod.yml裏配上open.eureka=true,其他的yml什麼也不寫就行了。這樣本地啓動時就相當於沒有開啓EnableDiscoveryClient。
使用場景還是蠻多的,具體的看情況,但是需要記住有這麼個註解,以便不時之需。