SpringBoot-Bean条件注入

2019-11-04 02:41:54 浏览数 (1)

  之前有篇文章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
代码语言:javascript复制
1、@ConditionalOnProperty(prefix = "ons",name = "type",havingValue = "mq")

配置ons.type=mq 生效

代码语言:javascript复制
2、@ConditionalOnProperty(prefix = "ons",name = {"type","env"},havingValue = "mq")

配置ons.type=mq 同时ons.env=mq 缺一不可才会生效

代码语言:javascript复制
3、@ConditionalOnProperty(prefix = "ons",name ="type",havingValue = "mq", matchIfMissing=true)

配置 没有也会生效 matchIfMissing=true

  • @ConditionalOnExpression
代码语言:javascript复制
1、@ConditionalOnExpression("${ons.type:true}")

配置ons.type=true时生效

代码语言:javascript复制
2、@ConditionalOnExpression("'${ons.type}'".equals('mq'))

配置ons.type=mq时生效

0 人点赞