通过条件注解@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;
    }
}
时间: 2024-07-31 23:20:10

通过条件注解@Conditional细粒度的选择bean实例的相关文章

条件注解@Conditional

通过活动的profile,可以获得不同的Bean.Spring4提供了一个更通用的基于条件的Bean的创建,即使用@Conditonal注解 @Conditional根据满足某一个特定条件创建一个特定的Bean. 比如:当某一个jar包在一个类路径下的时候,自动配置一个或多个Bean:或者只有某个Bean被创建才会创建另外一个Bean. 总的来说,就是根据特定条件来控制Bean的创建行为,利用这个特性可以进行一些自动的配置. 在SpringBoot中将会大量应用到条件注解. 原文地址:https

Spring_总结_04_高级配置(二)之条件注解@Conditional

一.前言 本文承接上一节:Spring_总结_04_高级配置(一)之Profile 在上一节,我们了解到 Profile 为不同环境下使用不同的配置提供了支持,那么Profile到底是如何实现的呢?其实Profile正是通过条件注解来实现的. 条件注解的应用场景举例: (1)希望一个或多个 bean 只有在应用的类路径下包含特定的库时才创建 (2)希望某个bean只有当另外某个特定bean也声明了之后才创建 (3)希望只有某个特定的环境变量设置之后,才会创建某个bean 上述场景能让我们联想到s

SpringBoot条件注解@Conditional

@Conditional是啥呀? @Conditional注解是个什么东西呢,它可以根据代码中设置的条件装载不同的bean,比如说当一个接口有两个实现类时,我们要把这个接口交给Spring管理时通常会只选择实现其中一个实现类,这个时候我们总不能使用if-else吧,所以这个@Conditional的注解就出现了. 我怎么用它呢? 在SpringBoot中,@Conditional注解并不是孤军奋斗,它们是一个家族,我们来看一下它们其中的几个成员,又都是怎么用的 @ConditionalOnBea

Spring条件注解@Conditional

@Conditional 基于条件的Bean的创建,根据满足某一个特定条件创建特定的Bean,通过实现Condition接口,并重写matches接口来构造判断条件. 下面的实例通过将以不同操作系统作为条件,我们将通过实现Condition接口,并重写其matchess方法来构造判断条件.若在Windows系统下运行程序,则输出列表命令为dir:若在Linux操作系统下运行程序,则输出列表命令为ls1.判断条件定义(1)判断Windows的条件 package com.lwh.highlight

JavaEE开发之Spring中的条件注解、组合注解与元注解

上篇博客我们详细的聊了<JavaEE开发之Spring中的多线程编程以及任务定时器详解>,本篇博客我们就来聊聊条件注解@Conditional以及组合条件.条件注解说简单点就是根据特定的条件来选择Bean对象的创建.条件注解就是可以根据不同的条件来做出不同的事情.在Spring中条件注解可以说是设计模式中状态模式的一种体现方式,同时也是面向对象编程中多态的应用部分.而组合注解就是将现有的注解进行组合.下方会给出具体的介绍和实例. 一.条件注解[email protected] 本篇博客的本部分

spring boot: 条件注解@Condition

@Conditional根据满足某一个特定的条件创建一个特定的Bean(基于条件的Bean的创建,即使用@Conditional注解). 比方说,当一个jar包在一个类的路径下的时候,自动配置一个或多个Bean,或者只有某个Bean被创建才会去创建另外一个Bean. 通过实现Condition接口,并重写期matches方法来构造判断条件.若在windows系统洗运行程序,则输出列表命令dir,若在linux操作系统下运行程序,则输出命令为:ls. 1.判断条件定义 判断windows的条件 1

全栈之路-杂篇-探究springBoot中的条件注解

这个是接上一个spring IOC注入机制中的进行继续探讨的,我们来继续探究OCP原则下的代码书写的问题,这个是利用条件注解. 一.条件注解的基本用法 这里还是之前的学习示例,简单的看一下 1.实体类的代码 这里有另个实体类,基本上就是一样的,只给出一个实体类的代码,另外,接口的代码也比较简单,不给出了,看的话,可以看上一篇那个中的代码 1 public class Diana implements ISkill { 2 3 private String skillName = "Diana R

峰哥说技术: 05-Spring Boot条件注解注解

Spring Boot深度课程系列 峰哥说技术—2020庚子年重磅推出.战胜病毒.我们在行动 05 峰哥说技术  Spring Boot条件注解 @EnableAutoConfiguration开启自动化配置,零配置就能运行,那么它的原理是什么?要理解这个,必须首先理解什么是条件注解.抛开 Spring Boot,我们来单纯的看看在 Spring 中条件注解的用法.首先我们来创建一个普通的 Maven 项目,然后引入 spring-context,如下 1)创建一个接口Food package

助力SpringBoot自动配置的条件注解ConditionalOnXXX分析--SpringBoo

注:该源码分析对应SpringBoot版本为2.1.0.RELEASE 1 前言 本篇接如何分析SpringBoot源码模块及结构?--SpringBoot源码(二) 上一篇分析了SpringBoot源码结构及各个模块pom之间的关系后,那么此篇开始就开始解开SpringBoot新特性之一--自动配置的神秘面纱了.因为SpringBoot自动配置原理是基于其大量的条件注解ConditionalOnXXX,因此,本节我们先来撸下Spring的条件注解的相关源码. 2 SpringBoot的派生条件