Spring - 源码阅读之 @Conditional 注解的用法及原理

概述

Spring 提供了 @Conditional 注解来根据条件判断是否注册组件到 IoC 容器

关于注解,不理解的可以查看 Java - 自定义注解 这篇文章

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

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

}

该注解可以用在以下几种方式:

  • 作为一个 类级别 的注解和 @Component 直接或间接注释在类上面,或者是标注了 @Configuration 的类
  • 作为一个 元注解 标注在 自定义的注解 上面
  • 作为一个 方法级别 的注解在任何 @Bean 修饰的方法上

注解中只有一个属性,是一个 Condition 类型的数组,组件必须满足所有 Condition 条件才会被注册到 IoC 容器

关于函数式接口,可以查看 Java8 - @FunctionalInterface 函数式接口 这篇文章

@FunctionalInterface
public interface Condition {

	/**
	 * Determine if the condition matches.
	 * @param context the condition context
	 * @param metadata the metadata of the {@link org.springframework.core.type.AnnotationMetadata class}
	 * or {@link org.springframework.core.type.MethodMetadata method} being checked
	 * @return {@code true} if the condition matches and the component can be registered,
	 * or {@code false} to veto the annotated component's registration
	 */
	boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);

}

举例

我们新建两个类:Rainumbrella,并使用 @Bean 注解标记为组件加入到 IoC 容器 中:

public class Rain {
}

public class Umbrella {
}

@Configuration
public class MyConfig2 {

    @Bean()
    public Rain rain() {
        return new Rain();
    }
    
    @Bean
    public Umbrella umbrella() {
        return new Umbrella();
    }
}

定义匹配条件:

public class MyCondition implements Condition {

    /**
     *
     * @param context 条件上下文
     * @param metadata 正在被检查的类或者方法的注解信息
     * @return
     */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // 获取类加载器
        ClassLoader classLoader = context.getClassLoader();
        // 获取 Bean 工厂
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        // 获取 BeanDefinition 注册中心
        BeanDefinitionRegistry registry = context.getRegistry();
        // 获取资源加载器
        ResourceLoader resourceLoader = context.getResourceLoader();
		// 获取当前应用的环境信息
        Environment environment = context.getEnvironment();
        String property = environment.getProperty("weather");
        return "rain".equals(property);
    }
}

Idea 中配置环境参数:

在这里插入图片描述

  • 修饰 @Bean 注解: 当获取到环境变量中存在 Weather 属性为 rain 的时候,才会把 Umbrella 加入到 IoC 容器
@Configuration
public class MyConfig2 {

    @Bean()
    public Rain rain() {
        return new Rain();
    }

    @Bean
    @Conditional(MyCondition.class)
    public Umbrella umbrella() {
        return new Umbrella();
    }
}

输出:

// 环境变量不等于 rain 时
myConfig2
rain

// 环境变量等于 rain 时
myConfig2
rain
umbrella
  • 修饰 @Configuration 类: 当获取到环境变量中存在 Weather 属性为 rain 的时候,才会把 Umbrella 以及 Rain 加入到 IoC 容器
@Configuration
@Conditional(MyCondition.class)
public class MyConfig2 {

    @Bean()
    public Rain rain() {
        return new Rain();
    }

    @Bean
    public Umbrella umbrella() {
        return new Umbrella();
    }
}

输出:

// 环境变量不等于 rain 时
配置类包括其中的 Bean 都不会注册到 IoC 容器中

// 环境变量等于 rain 时
myConfig2
rain
umbrella

原理

参考 Spring - IoC 容器创建过程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值