通過條件注解@Conditional細粒度的選擇bean實例


在進行spring進行開發時,當某個接口有多種實現方式並且我們只想讓一種生效時,比如聲明如下一個接口和兩個實現:

public interface LanggageService {
      String say();
}
public class ChineseServiceImpl implements LanggageService {
    @Override
    public String say() {
        return "你好";
    }
}
public class EnglishServiceImpl implements LanggageService {
    @Override
    public String say() {
        return "hello";
    }
}

我們通常使用xml為某個接口配置實現類;

    <bean id="languageService" class="com.liam.service.ChineseServiceImpl"></bean>

當然后來我們習慣使用注解的方式了,比如

   @Bean
    public LanggageService englishService(){
        return new EnglishServiceImpl();
     }

當然也可以通過@Component進行掃描注入,這也是為了去除java令人發指的諸多xml配置的一項進步,所以當使用spring boot進行開發時,我們盡量摒棄了諸多配置,不管是Hibernate,JPA亦或者是mybatis...

但是也顯然,有時候我們需要通過配置來選擇我們使用的bean,基於xml還好,但是基於注解的話通過重新編譯打包顯然是不能接受的。。比如測試環境我們設置的數據源是mysql,生產環境換成oracle了,當然我們通常使用的是profile進行配置,但還是不夠靈活,我們需要更細粒度的管理bean..所以也就有了Conditional。。。(廢話連篇。。。)

比如我們在spring boot中要通過application.properties中進行配置來選擇我們使用的bean

say.method=chinese

則可以聲明兩個Condition

public class SayChineseCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
      String m=  conditionContext.getEnvironment().getProperty("say.method").toString();
        boolean isChi= "chinese".equals(m);
        System.err.println("current chinese   "+ isChi);
        return isChi;
    }
}
public class SayEnglishCondition implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
      String m=  conditionContext.getEnvironment().getProperty("say.method").toString();
        boolean isEn= "english"==m;
        System.err.println("current english   "+ isEn);
        return isEn;
    }
}

然后實現類中配置上對應的Conditional:

@Service
@Conditional(SayChineseCondition.class)
public class ChineseServiceImpl implements LanggageService {
    @Override
    public String say() {
        return "你好";
    }
}

簡單,靈活。

此處需要注意的是application.properties在spring boot中屬於環境變量級別的配置加載,所以優先級較高,假如通過其他配置文件進行加載時借助PropertySource或者ConfigurationProperties之類的是不能如願的,因為加載Condition時,我們的配置bean尚未加載,比如下面的方式是無效的。

@PropertySource(value = "first.properties")
public class SayEnglishCondition implements Condition {
    @Value("${say.method}")
    private String lang;
    public String getLang() {
        return lang;
    }
    public void setLang(String lang) {
        this.lang = lang;
    }
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        String m=lang;//  conditionContext.getEnvironment().getProperty("say.method").toString();
        boolean isEn= "english".equals(m);
        System.err.println("current english   "+ isEn);
        return isEn;
    }
}

所以。。我們只能手動加載了。。

public class SayEnglishCondition implements Condition { 
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        Properties properties = new Properties();
        try {
            properties.load(conditionContext.getResourceLoader().getResource("first.properties").getInputStream());
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        boolean isEn = "english".equals(properties.getProperty("say.method"));
        System.err.println("current english   " + isEn);
        return isEn;
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM