ContiionalOnXXX
在实际应用中,时常会碰到在某些情况下,才需要创建Bean或者启用某些配置。这个时候就是Conditional的应用场景
自定义的condition
Condition接口定义了一个入口条件,通过返回true/false来触发其是否要执行操作:
接口定义如下:
@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);
}
各位读者所要做的就是直接接口,实现具体的逻辑判断条件即可。
这里基于ProfileCondition的实现来介绍其具体使用,直接上代码:
class ProfileCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
if (attrs != null) {
for (Object value : attrs.get("value")) {
if (context.getEnvironment().acceptsProfiles((String[]) value)) {
return true;
}
}
return false;
}
return true;
}
}
上述的条件为profile中的名称必须为环境中可以接受的profile列表内容,才可以被接受,被启用和激活。
一般profile的标注使用方法如下:
@Configuration
@Profile("AAA")
@ProfileCondition
public class ProductionConfiguration {
//configuration info
}
其表示仅仅在Profile为AAA的情况下,且production为项目中可以接受的profile列表之内,才会创建ProductionConfiguration的实例配置内容。
Spring提供的条件Bean
@ConditionalOnBean(仅仅在当前上下文中存在某个对象时,才会实例化一个Bean)
@ConditionalOnClass(某个class位于类路径上,才会实例化一个Bean),该注解的参数对应的类必须存在,否则不解析该注解修饰的配置类;
@ConditionalOnExpression(当表达式为true的时候,才会实例化一个Bean)
@ConditionalOnMissingBean(仅仅在当前上下文中不存在某个对象时,才会实例化一个Bean), 该注解表示,如果存在它修饰的类的bean,则不需要再创建这个bean;可以给该注解传入参数例如@ConditionOnMissingBean(name = “example”),这个表示如果name为“example”的bean存在,这该注解修饰的代码块不执行。
@ConditionalOnMissingClass(某个class类路径上不存在的时候,才会实例化一个Bean)
@ConditionalOnNotWebApplication(不是web应用)
@ConditionalOnProperty是指在application.yml里配置的属性是否为true,其他的几个都是对class的判断
总结
condition的使用核心解决了根据不同的条件动态解析或者创建某些bean操作的方式,无需硬编码这些逻辑,直接使用这些标注就可以了。