Spring注解驱动开发-@Conditional

源码解析

  • 这个注解可以用来创建条件,来决定在什么情况下创建哪些bean对象

  • 首先看源码

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
​
package org.springframework.context.annotation;
​
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
​
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {
    Class<? extends Condition>[] value();
}
  • 从源码可以看出来,这个注解有一个value属性,该属性返回的是一个继承了Condition接口的一个类所构成的一个数组。

  • 看一下Condition接口是一个什么样的接口,上源码

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
​
package org.springframework.context.annotation;
​
import org.springframework.core.type.AnnotatedTypeMetadata;
​
public interface Condition {
    boolean matches(ConditionContext var1, AnnotatedTypeMetadata var2);
}
  • 可以看到,Condition接口中有一个方法matches,该方法的返回值是一个boolean值。因为Condition本来就是用来构造条件的,所以说满足条件的话就返回true,不满足条件的话就返回flase。

  • matches方法有两个参数,一个是ConditionContext类型的,另一个是AnnotatedTypeMetadata类型的。

  • ConditionContext,是判断条件使用的上下文

  • AnnotatedTypeMetadata,是注释信息

  • ConditionContext是一个接口,里面有五个get方法,对应五种返回值,分别能够得到

package org.springframework.context.annotation;
​
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
​
public interface ConditionContext {
//借助getRegistry()返回的BeanDefinitionRegistry可以检查bean定义    
    BeanDefinitionRegistry getRegistry();
//借助getBeanFactory()返回的ConfigurableListableBeanFactory检查bean是否存在,甚至探查bean的属性
    ConfigurableListableBeanFactory getBeanFactory();
//借助getEnvironment()返回的Environment检查环境变量是否存在以及它的值是什么
    Environment getEnvironment();
//借助getResourceLoader()返回的ResourceLoader所加载的资源
    ResourceLoader getResourceLoader();
//借助getClassLoader()返回的ClassLoader加载并检查类是否存在
    ClassLoader getClassLoader();
}

  • matches方法的第二个参数是AnnotatedTypeMetadata类型的

  • 看一下源码:

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
​
package org.springframework.core.type;
​
import java.util.Map;
import org.springframework.util.MultiValueMap;
​
public interface AnnotatedTypeMetadata {
   
    boolean isAnnotated(String var1);
    
    Map<String, Object> getAnnotationAttributes(String var1);
​
    Map<String, Object> getAnnotationAttributes(String var1, boolean var2);
​
    MultiValueMap<String, Object> getAllAnnotationAttributes(String var1);
​
    MultiValueMap<String, Object> getAllAnnotationAttributes(String var1, boolean var2);
}

  • 具体使用:

  • 当我们想要自己构造田间决定创建哪些bean对象的时候,可以new一个class,这个class实现Conditional接口,覆写matches方法。这个class的作用就是构造条件。

  • 当matches方法返回true,按照所构造的条件来决定创建哪些bean。

  • 当matches方法返回flase,不按照所构造的条件来决定创建哪些bean。

例子

  • 根据环境是Linux还是Windows来决定加载哪些bean

以下的两个class都实现了Condition类
使用ConditionContext参数获取到了当前程序运行的环境是linux还是Windows
返回true或flase
package cr.condition;
​
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
​
/**
 * @Author cr
 * @Date 2022/10/7 19:20
 */
public class MacConditional implements Condition {
​
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        //获取运行环境
        Environment environment = conditionContext.getEnvironment();
        String osName = environment.getProperty("os.name");
        if (osName.contains("Mac")){
            return true;
        }
        return false;
    }
}
package cr.condition;
​
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;
​
/**
 * @Author cr
 * @Date 2022/10/7 19:26
 */
public class WindowsConditional implements Condition {
    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        Environment environment = conditionContext.getEnvironment();
        String osName = environment.getProperty("os.name");
        if (osName.contains("Windows")){
            return true;
        }
        return false;
    }
}

  • 在注入bean的类中,在@Bean修饰的方法头上,加上注释@Conditional。并且该注释的属性的返回值是一个类(该类继承于Condition,也就是以上的两个class)

@Configuration
public class MainConfig2 {
    
    //如果为Windows环境则创建windows对象
    @Conditional({WindowsConditional.class})
    @Bean("windows")
    public Person getBill() {
        return new Person("windows操作系统",40) ;
    }
    
    
    //如果为Mac环境则创建mac对象
    @Conditional({MacConditional.class})
    @Bean("mac")
    public Person getlinux() {
        return new Person("mac",45) ;
    }
}

来源:blbl雷丰阳Spring讲解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值