美文网首页
Spring注解驱动开发系列-@Conditional

Spring注解驱动开发系列-@Conditional

作者: lclandld | 来源:发表于2020-04-23 16:22 被阅读0次
  • 这个注解是Spring4新提供的,它的作用是按照一定的条件进行判断,满足条件给容器注册bean
  • 在SpringBoot底层大量使用到,所有很重要(因为实际项目中有用到@ConditionalOnProperty这个注解)


    image.png

    现在还是来说说这个注解的一些定义和具体使用,对于SpringBoot中的使用,后期我会逐步慢慢学习

一、接口定义

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

    /**
     * All {@link Condition}s that must {@linkplain Condition#matches match}
     * in order for the component to be registered.
     */
    Class<? extends Condition>[] value();

}

根据定义可以知道以下几点:

  • 此注解用到类和方法上
  • 注解的值是一个Class数组,且Class必须继承Condition接口实现matches方法,matches方法返回值是boolean,true表示注入bean,false表示不注入bean
public interface Condition {
    /**
     * ConditionContext:判断条件能使用的上下文(环境)
     * AnnotatedTypeMetadata:注释信息
     */
    boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);

}

2、简单的demo

eg:注册两个Person,一个bill,一个linus,默认情况下这两个人一定都在容器中,涉及到一个Person类,一个配置类,一个测试用例

  • Person类
@Data
@Component
@AllArgsConstructor
public class Person {
    private String name;
    private Integer age;

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
}
  • 配置类()
@Configurable
//@ComponentScan(value = "com.test",excludeFilters ={@Filter(type = FilterType.CUSTOM,value = MyTypeFilter.class)})
public class Config {
    @Bean
    public Person  person(){
        return new Person();
    }
    @Bean("bill")
    public Person  person1(){
        return new Person("Bill Gates",62);
    }
    @Bean("linus")
    public Person person02(){
        return new Person("linus", 48);
    }
}

  • 测试用例获取容器中所有的bean
  @org.junit.Test
    public void testComponentScan() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);
        String[] definitionNames = applicationContext.getBeanDefinitionNames();
        for (String name : definitionNames) {
            System.out.println(name);
        }
    }
  • 结果(可以看到不加任何条件的情况下,bill和linus这两个bean都加入到容器中了)


    image.png
  • 要求,如果当前系统是windows系统(WindowsCondition)就注册bill,如果是Linux系统(LinuxCondition)就注册linus
  • LinuxCondition.class
//判断是否linux系统
public class LinuxCondition implements Condition {
    /**
     * ConditionContext:判断条件能使用的上下文(环境)
     * AnnotatedTypeMetadata:注释信息
     */
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // TODO是否linux系统
        //1、能获取到ioc使用的beanfactory
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        //2、获取类加载器
        ClassLoader classLoader = context.getClassLoader();
        //3、获取当前环境信息
        Environment environment = context.getEnvironment();
        //4、获取到bean定义的注册类
        BeanDefinitionRegistry registry = context.getRegistry();
        
        String property = environment.getProperty("os.name");
        
        //可以判断容器中的bean注册情况,也可以给容器中注册bean
        boolean definition = registry.containsBeanDefinition("person");
        if(property.contains("linux")){
            return true;
        }
        
        return false;
    }
}
  • WindowsCondition.class
//判断是否windows系统
public class WindowsCondition implements Condition {

    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();
        String property = environment.getProperty("os.name");
        if(property.contains("Windows")){
            return true;
        }
        return false;
    }

}
  • 修改配置类
    在bill的bean上加上注解@Conditional(value = WindowsCondition.class)
    在linus的bean上加上注解@Conditional(value = LinuxCondition.class)
    @Conditional(value = WindowsCondition.class)
    @Bean("bill")
    public Person  person1(){
        return new Person("Bill Gates",62);
    }
    @Conditional(value = LinuxCondition.class)
    @Bean("linus")
    public Person person02(){
        return new Person("linus", 48);
    }
  • 运行结果(Windows系统运行的,所以只注册了lill)


    image.png
  • 运行Linux系统的结果(不能运行在Linux系统下,可以通过修改运行时参数)
    这里写的是-Doa.name=linux这个linux是小写的,因为我在LinuxCondition.class的添加写的是linux


    修改参数模拟Linux系统下
image.png

注意
1、上面记录的是将注解标注在方法上的,当然也可以标注到类上,如果将@Conditional(value = WindowsCondition.class)标注到类上,Windows环境下,bill和linus以及其他所有的bean都会被注入到容器中,linux环境下,这个配置类中的所有bean都不会被注入
2、@Conditional里面可以加入多个条件类,加入多个条件的结论是:
所有条件都必须为true才能注入容器中,只要一个条件为false,则不能注入

相关文章

网友评论

      本文标题:Spring注解驱动开发系列-@Conditional

      本文链接:https://www.haomeiwen.com/subject/khsoihtx.html