前言
Spring Boot系列: 点击查看Spring Boot系列文章
@Conditional注解
这个注解在Spring4中引入,其主要作用就是判断条件是否满足,从而决定是否初始化并向容器注册Bean
声明:
//作用域为类或者方法上
@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();
}
可以看到,Conditional注解只有一个value属性, value属性为一个Class数组,并且需要实现Condition接口的类。
Condition接口
Condition接口只有一个matches方法,这个方法是用来确定条件是否匹配。返回true表示条件匹配,组件可以被注册。返回false则不能注册
public interface Condition {
boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata);
}
matches方法
matches方法有两个参数,一个为ConditionContext (条件上下文),通过它我们可以获取很多有用的信息。AnnotatedTypeMetadata 为注解元数据
以下为ConditionContext 的源码方法
public interface ConditionContext {
/**
*返回一个BeanDefinitionRegistry ,BeanDefinitionRegistry 包含了bean的注册信息和我们定义bean的信息
*/
BeanDefinitionRegistry getRegistry();
/**
* 返回保存bean的bean工厂(BeanFactory),从BeanFactory,我们可以获取容器中的任意一个bean
*/
@Nullable
ConfigurableListableBeanFactory getBeanFactory();
/**
* 返回当前的运行环境,environment 持有所有的配置信息
*/
Environment getEnvironment();
/**
* 返回当前使用的资源加载器
*/
ResourceLoader getResourceLoader();
/**
* 返回 类加载器
*/
@Nullable
ClassLoader getClassLoader();
}
@Conditional使用
下面,我来演示一下如何通过配置文件和@Conditional注解来控制一个bean的注册
1、首先,我们创建一个实现Condition 接口的类,在该类上的matches方法写相应的条件判断。我这里是通过配置文件的"is.open.condition"属性是否为true,如果不为true则返回false,则不能注册组件。为true则注册组件。
public class OpenConditonal implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
Boolean property = context.getEnvironment().getProperty("is.open.condition",boolean.class);
if (property!=null&&property){
return true;
}
return false;
}
}
2、在配置类的注册方法加上 @Conditional注解,参数是我们上面定义的条件类,这样bean的注册就要通过我们定义的条件类才能注册
@Configuration
public class ConditionConfig {
@Bean
@Conditional(OpenConditonal.class)
public Teacher teacher(){
Teacher teacher=new Teacher();
teacher.setId("1");
teacher.setAge("20");
System.out.println("注册teacher类");
return teacher;
}
}
3、结果
当我在配置文件加上is.open.condition=true,bean能成功注册,在控制台输出注册teacher类
当我没在配置文件加is.open.condition,或者填false时,bean不能注册
注意:当我们在其他bean注入一些可能不存在的bean时,最好将required属性设为false,这样避免bean不存在时报错
例:
@Autowired(required = false)
private xxxBean xxxBean
@Conditional的派生注解
注解 说明
@ConditionalOnSingleCandidate 当给定类型的bean存在并且指定为Primary的给定类型存在时,返回true
@ConditionalOnMissingBean 当给定的类型、类名、注解、昵称在beanFactory中不存在时返回true.各类型间是or的关系
@ConditionalOnBean 与上面相反,要求bean存在。例:@ConditionalOnBean(name="redisTemplate")
@ConditionalOnMissingClass 当给定的类名在类路径上不存在时返回true,各类型间是and的关系
@ConditionalOnClass 与上面相反,要求类存在
@ConditionalOnCloudPlatform 当所配置的CloudPlatform为激活时返回true
@ConditionalOnExpression spel表达式执行为true
@ConditionalOnJava 运行时的java版本号是否包含给定的版本号.如果包含,返回匹配,否则,返回不匹配
@ConditionalOnProperty 要求配置属性匹配条件
@ConditionalOnJndi 给定的jndi的Location 必须存在一个.否则,返回不匹配
@ConditionalOnNotWebApplication web环境不存在时
@ConditionalOnWebApplication web环境存在时
@ConditionalOnResource 要求制定的资源存在