Spring(学习笔记)-条件注解@Profile深入理解!

重点标识

条件注解,顾名思义,满足条件的情况下,才会生效。
条件满足的时候,bean才会被注册到Spring容器中。
自定义条件注解案例。
开发,测试,生产多环境切换案例。
自定义多环境切换案例。

案例演示

这里以动物叫声来进行演示,简单点,分为猫和狗都实现了叫声的接口,也都想要注入Spring容器中,但是到底要注入哪一个呢,有条件来决定。

接口

public interface Animal {
    String call();
}

实现类


public class Dog implements Animal{
    @Override
    public String call() {
        return "汪汪汪!";
    }
}


public class CatCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return true;
    }
}

进行条件判断,注意,这里简单点,只是为了表达条件注解的意思,实现了Condition接口后,实现它里面的matches方法,返回为true,则代表条件通过,反之就是不通过,大家可以自己发挥。


public class CatCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return true;
    }
}

public class DogCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        return false;
    }
}

进行配置,注入Spring容器,注意,这里的@Conditional()注解,就是条件注解,而且,必须条件为true,他才会注入到Spring容器中,而不是都注入了,再根据条件去获取。


@Configuration
public class JavaConfig {

    @Bean
    @Conditional(DogCondition.class)
    Animal dog(){
        return new Dog();
    }

    @Bean
    @Conditional(CatCondition.class)
    Animal cat(){
        return new Cat();
    }
}

```测试类
```java

public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ant = new AnnotationConfigApplicationContext(JavaConfig.class);
        Animal bean = ant.getBean(Animal.class);
        System.out.println(bean.call());
    }
}

自然,这里输出的就是猫的叫声了。

在java日常开发中,我们常用的是多环境切换,实际上就是条件注解的plus版,这里可以写一个简单的例子,深入学习一下。

先准备一个DatsSource类,作为数据源


public class DataSource {

    private String url;
    private String username;
    private String password;


    @Override
    public String toString() {
        return "DataSource{" +
                "url='" + url + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }

    public DataSource() {
    }

    public DataSource(String url, String username, String password) {
        this.url = url;
        this.username = username;
        this.password = password;
    }
}

进行注入,注意这次使用了环境切换注解,也就是@profile(),指定环境。


@Configuration
public class JavaConfig {
    @Bean
    @Profile("dev")
    DataSource dev(){
        return new DataSource("jdbc:///dev","dev","dev");
    }
    @Bean
    @Profile("prod")
    DataSource prod(){
        return new DataSource("jdbc:///prod","prod","prod");
    }
 }

进行测试,这里需要注意,不能像之前那样,直接加载配置文件了,因为加载配置文件,就会初始化容器注入,bean因为条件没有一个满足的,所以两个都不是注入容器。
这里进行指定环境,然后再加载配置文件,最后刷新容器,就能拿到对应的值了。

    public static void main(String[] args) {
        AnnotationConfigApplicationContext ant = new AnnotationConfigApplicationContext();
        ant.getEnvironment().addActiveProfile("dev");
        ant.register(JavaConfig.class);
        ant.refresh();

        DataSource bean = ant.getBean(DataSource.class);
        System.out.println(bean);
    }

可以进入到@Profile源码中看一下,我们可以发现,本质上还是@Conditional注解在起作用。
在这里插入图片描述

最后,我们可以模仿官方的profile自己写一个myprofile来验证一下猜想。

新建一个注解类。


@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional({MyProfileCondition.class})
public @interface MyProfile {

    String[] en();
}

自定义MyProfileCondition,这里需要注意,matadata后面那部分,实际上就是找到JavaConfig配置中,使用了MyProfile注解的bean,后面则是迭代并把en属性提取出来。


public class MyProfileCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(MyProfile.class.getName());
        if (attrs != null) {
            Iterator var4 = ((List)attrs.get("en")).iterator();

            Object value;
            do {
                if (!var4.hasNext()) {
                    return false;
                }

                value = var4.next();
            } while(!context.getEnvironment().matchesProfiles((String[])value));

            return true;
        } else {
            return true;
        }
    }
}

完了之后,在JavaConfig中进行配置,实际上和profile没什么区别,如下:


@Configuration
public class JavaConfig {


    @Bean
    @MyProfile(en="dev")
    DataSource dev(){
        System.out.println("dev");
        return new DataSource("jdbc:///dev","dev","dev");
    }
    @Bean
    @MyProfile(en="prod")
    DataSource prod(){
        System.out.println("prod");
        return new DataSource("jdbc:///prod","prod","prod");
    }

进行测试,结果自然是ok的。

public static void main(String[] args) {
        AnnotationConfigApplicationContext ant = new AnnotationConfigApplicationContext();
        ant.getEnvironment().addActiveProfile("dev");
        ant.register(JavaConfig.class);
        ant.refresh();

        DataSource bean = ant.getBean(DataSource.class);
        System.out.println(bean);
    }
  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值