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

2020-04-23  本文已影响0人  lclandld

一、接口定义

@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();

}

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

public interface Condition {
    /**
     * ConditionContext:判断条件能使用的上下文(环境)
     * AnnotatedTypeMetadata:注释信息
     */
    boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);

}

2、简单的demo

eg:注册两个Person,一个bill,一个linus,默认情况下这两个人一定都在容器中,涉及到一个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);
    }
}

  @org.junit.Test
    public void testComponentScan() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Config.class);
        String[] definitionNames = applicationContext.getBeanDefinitionNames();
        for (String name : definitionNames) {
            System.out.println(name);
        }
    }
//判断是否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;
    }
}
//判断是否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;
    }

}
    @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);
    }
image.png

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

上一篇 下一篇

猜你喜欢

热点阅读