@Conditional介绍

首先我们先了解一下@Conditional注解,@Conditional是Spring4新提供的注解,它的作用是按照一定的条件进行判断,需要注入的Bean满足给定条件才可以注入到Spring IOC容器中。

  • 作用:根据是否满足某一个特定条件来决定是否创建某个特定的Bean
  • 意义:Springboot实现自动配置的关键基础能力
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Conditional {

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

}

从注解的定义我们可以看到,使用该注解我们需要传入的是一个Class数组,并且这些Class必须实现Condition接口,Condition接口定义如下:

@FunctionalInterface
public interface Condition {

	/**
	 * Determine if the condition matches.
	 * @param context the condition context
	 * @param metadata 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);

}

实现Condition接口必须实现matches方法,matches方法由子类实现(判断条件是否匹配)返回true,代表@Conditional注解的Bean可以被注入到Spring IOC容器,返回false,@Conditional注解的Bean就不会被注入到Spring IOC容器。

spirngboot中常用的@Conditional注解

  • @ConditionalOnBean(存在某个bean的时候实例化)
  • @ConditionalOnMissingBean(不存在某个bean的时候实例化)
  • @ConditionalOnClass(存在某个类时,才会实例化一个Bean)
  • @ConditionalOnSingleCandidate(指定Bean在容器中只有一个,或者虽然有多个但是指定首选Bean)
  • @ConditionalOnMissingClass(不存在某个类时,才会实例化一个Bean)
  • @ConditionalOnWebApplication(如果是Web应用)
  • @ConditionalOnProperty(控制配置类是否生效)
  • @ConditionalOnNotWebApplication(如果不是Web应用)
  • @ConditionalOnJava(如果是Java应用)
  • @ConditionalOnResource(对指定资源进行校验)

我们来看看@ConditionalOnBean注解

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

@Conditional(OnBeanCondition.class),那么OnBeanCondition这个类应该实现了Condition

在这里插入图片描述

具体逻辑不细究,我们可以自己实现一个这样的注解。

自定义

实现步骤

  • 编写注解类,类上标注@Conditional的实现
import org.springframework.context.annotation.Conditional;

import java.lang.annotation.*;

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

    String[] value() default {};

}
  • Conditional的实现类
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.StringUtils;


public class MyCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        /**
         * 获取注解值
         */
        String[] properties = (String[])metadata.getAnnotationAttributes("com.bushro.condi.MyConditionAnnotation").get("value");
        for (String property : properties) {
            //环境变量中有这些变量则匹配成功
            if (StringUtils.isEmpty(context.getEnvironment().getProperty(property))) {
                return false;
            }
        }
        return true;
    }
}
  • 配置使用
@Component
@ConfigurationProperties(prefix = "bushro")
@MyConditionAnnotation({"test1", "test2"})
public class MyConfig {
    private String condition;

    public String getCondition() {
        return condition;
    }

    public void setCondition(String condition) {
        this.condition = condition;
    }
}

application.properties配置

bushro.condition=test
test1=xxx
test2=xxx
  • 测试看能不能获取到MyConfig这个bean,然后去掉test1的配置再试试
    @Test
    public void testA() {
        MyConfig bean = applicationContext.getBean(MyConfig.class);
        System.out.println(bean.getCondition());
    }

版权声明:本文为BushQiang原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/BushQiang/article/details/125287800