@ConditionalOnProperty用于多值属性

时间:2016-06-22 13:13:03

标签: java spring spring-boot yaml

有没有办法使用基于多值属性的@ConditionalOnProperty注释?

Spring配置:

@Bean
@ConditionalOnProperty(name = "prop", havingValue = "a")
public SomeBean bean1() {
    return new SomeBean1();
}

@Bean
@ConditionalOnProperty(name = "prop", havingValue = "b")
public SomeBean bean2() {
    return new SomeBean2();
}

和application.yaml

prop: 
 - a
 - b

我希望两个bean:bean1和bean2都将在spring上下文中注册,但是没有人注册。有没有办法做到这一点?

2 个答案:

答案 0 :(得分:2)

看起来@ConditionalOnProperty没有多元化的特性。 在春天的环境中,它们被表示为

@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnPropertyCondition.class)
public @interface ConditionalOnProperty2 {
    String name();
    String value();
}

我的解决方案是创建自己的@Conditional扩展,它可以使用多值属性。这是一个例子。

注释:

class OnPropertyCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String name = attribute(metadata, "name");
        String value = attribute(metadata, "value");

        String searchName = name;
        String property = property(context, searchName);
        int i = 0;
        do {
            if (value.equals(property)) return true;
            searchName = name + '[' + i++ + ']';
        } while ((property = property(context, searchName)) != null);
        return false;
    }

    private String attribute(AnnotatedTypeMetadata metadata, String name) {
        return (String) metadata.getAnnotationAttributes(ConditionalOnProperty2.class.getName()).get(name);
    }

    private String property(ConditionContext context, String name) {
        return context.getEnvironment().getProperty(name);
    }
}

条件:

 @Bean
 @ConditionalOnProperty2(name = "prop", havingValue = "a")
 public SomeBean bean1() {
     return new SomeBean1();
 }

 @Bean
 @ConditionalOnProperty2(name = "prop", havingValue = "b")
 public SomeBean bean2() {
     return new SomeBean2();
 }

用法:

{{1}}

答案 1 :(得分:1)

您可以使用Spring Boot @ConditionalOnExpression批注,不仅可以在@ bean-annotated方法中使用,还可以直接在类上使用:

@ConditionalOnExpression("${my.prop}")
@Component
class SomeBean1 implements SomeBean {}

@ConditionalOnExpression("!${my.prop}")
@Component
class SomeBean2 implements SomeBean {}

话虽如此,我个人更喜欢使用纯Java:

@Value("${my.prop}") String myProp;
...
@Bean SomeBean someBean() {
    if ("abc".equals(myProp)) {return new SomeBean1();} else {return new SomeBean2();}
}