這個需求應該也比較常見,在不一樣的條件下建立不一樣的bean,具體場景不少,能看到這篇的確定懂個人意思。html
假若不瞭解spring4.X新加入的@Conditional註解的話,要實現不一樣條件建立不一樣的bean仍是比較麻煩的,可能須要硬編碼一些東西作if判斷。那麼如今有個@Conditional註解後,事情就簡單多了。用法很簡單,直接上代碼。web
新建一個springboot項目,添加一個Configuration標註的類,咱們經過不一樣的條件表達式來建立bean。spring
-
package com.tianyalei.condition;
-
-
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
-
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
-
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-
import org.springframework.context.annotation.Bean;
-
import org.springframework.context.annotation.Conditional;
-
import org.springframework.context.annotation.Configuration;
-
-
/**
-
* Created by wuweifeng on 2017/10/11.
-
*/
-
@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的類,裏面是空的就行。express
-
import org.springframework.context.annotation.Condition;
-
import org.springframework.context.annotation.ConditionContext;
-
import org.springframework.core.type.AnnotatedTypeMetadata;
-
-
/**
-
* Created by wuweifeng on 2017/10/11.
-
*/
-
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就不建立,就這麼簡單。springboot
這些註解裏的條件能夠是多個,也能夠賦默認值,也能夠標註在類上,若是標註在類上,則對類裏的全部@Bean方法都生效。app
其中@ConditionalOnProperty是指在application.yml裏配置的屬性是否爲true,其餘的幾個都是對class的判斷。ide
我在配置里加上abc.property = true這個配置就能夠測試上面的代碼了。測試
而後再來一個對類進行多個條件標註的例子:flex
-
package com.tianyalei.condition;
-
-
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
-
import org.springframework.context.annotation.Bean;
-
import org.springframework.context.annotation.Configuration;
-
-
/**
-
* Created by wuweifeng on 2017/10/11.
-
*/
-
@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註解來解決它。
-
/**
-
* @author wuweifeng wrote on 2017/11/25.
-
* 根據部署環境動態決定是否啓用eureka
-
*/
-
@Component
-
@ConditionalOnProperty(value = "open.eureka")
-
@EnableDiscoveryClient
-
public class JudgeEnableDiscoveryClient {
-
}
若是我只想讓線上的環境開啓eureka,那麼我就在application-prod.yml裏配上open.eureka=true,其餘的yml什麼也不寫就好了。這樣本地啓動時就至關於沒有開啓EnableDiscoveryClient。
使用場景仍是蠻多的,具體的看狀況,可是須要記住有這麼個註解,以便不時之需。