之前有篇文章Springboot 排除不想加载的配置只是排除,如果有些复杂场景需要根据条件来判断 就需要Spring 支持的另外一种方式 ——@Conditional注解。
借此来看下Spring对于条件注入的支持
@Conditional
定义Condition
代码语言:javascript复制public class MetaqCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String property = context.getEnvironment().getProperty("ons.type");
return "metaq".equalsIgnoreCase(property);
}
}
public class MqCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String property = context.getEnvironment().getProperty("ons.type");
return "mq".equalsIgnoreCase(property);
}
}
java config
代码语言:javascript复制@Configuration
@Slf4j
public class ConditionalAutoConfig {
@Bean
@Conditional(MqCondition.class)
public Consumer mqConsumerCondition() {
Properties properties = new Properties();
properties.put("AccessKey", "accessKey");
properties.put("SecretKey", "secretKey");
properties.put("ONSAddr", "http://onsaddr-internet.aliyun.com/rocketmq/nsaddr4client-internet");
properties.put("ConsumerId", "iotConsumerId");
Consumer consumer = ONSFactory.createConsumer(properties);
log.info("create mq consumer");
return consumer;
}
@Bean
@Conditional(MetaqCondition.class)
public MetaPushConsumer metaPushConsumer() {
MetaPushConsumer consumer = new MetaPushConsumer("consumerId");
log.info("create metaq consumer");
return consumer;
}
}
配置文件
ons.type=mq
启动项目 log输出 create mq consumer
Conditional 如何解析 看下AnnotatedBeanDefinitionReader.doRegisterBean()
代码语言:javascript复制<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
//将配置类信息转成AnnotatedGenericBeanDefinition
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
//@Conditional装配条件判断是否跳过注册
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
······
扩展
- @ConditionalOnBean:当容器中有指定Bean的条件下。
- @ConditionalOnClass:当classpath类路径下有指定类的条件下。
- @ConditionalOnCloudPlatform:当指定的云平台处于active状态时。
- @ConditionalOnExpression:基于SpEL表达式的条件判断。
- @ConditionalOnJava:基于JVM版本作为判断条件。
- @ConditionalOnJndi:在JNDI存在的条件下查找指定的位置。
- @ConditionalOnMissingBean:当容器里没有指定Bean的条件。
- @ConditionalOnMissingClass:当类路径下没有指定类的条件下。
- @ConditionalOnNotWebApplication:当项目不是一个Web项目的条件下。
- @ConditionalOnProperty:当指定的属性有指定的值的条件下。
- @ConditionalOnResource:类路径是否有指定的值。
- @ConditionalOnSingleCandidate:当指定的Bean在容器中只有一个,或者有多个但是指定了首选的Bean。
- @ConditionalOnWebApplication:当项目是一个Web项目的条件下
案例
- @ConditionalOnProperty
1、@ConditionalOnProperty(prefix = "ons",name = "type",havingValue = "mq")
配置ons.type=mq
生效
2、@ConditionalOnProperty(prefix = "ons",name = {"type","env"},havingValue = "mq")
配置ons.type=mq 同时ons.env=mq
缺一不可才会生效
3、@ConditionalOnProperty(prefix = "ons",name ="type",havingValue = "mq", matchIfMissing=true)
配置 没有也会生效 matchIfMissing=true
- @ConditionalOnExpression
1、@ConditionalOnExpression("${ons.type:true}")
配置ons.type=true
时生效
2、@ConditionalOnExpression("'${ons.type}'".equals('mq'))
配置ons.type=mq
时生效