@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 版权协议,转载请附上原文出处链接和本声明。