Spring @ConditionalOnProperty havingValue = “value1” or “value2”

青春壹個敷衍的年華 提交于 2020-04-08 04:54:05

问题


I am looking for configurationOnProperty usage where I can specify to consider more than one value as shown below

Eg: @ConditionalOnProperty(value = "test.configname", havingValue = "value1" or "value2")

OR

I would like to know if it is possible to specify confiugrationOnProperty with condition of havingValue != "value3"

Eg: @ConditionalOnProperty(value = "test.configname", havingValue != "value3")

Please let me know if there is a way to achieve any one of the above in spring boot configuration.


回答1:


Spring Boot provides AnyNestedCondition for created a condition that will match when any nested condition matches. It also provides AllNestedConditions and NoneNestedConditions for matching when all nested conditions or no nested conditions match respectively.

For your specific case where you want to match a value of value1 or value2 you would create an AnyNestedCondition like this:

class ConfigNameCondition extends AnyNestedCondition {

    public ConfigNameCondition() {
        super(ConfigurationPhase.PARSE_CONFIGURATION);
    }

    @ConditionalOnProperty(name = "test.configname", value = "value1")
    static class Value1Condition {

    }

    @ConditionalOnProperty(name = "test.configname", value = "value2")
    static class Value2Condition {

    }

}

And then use it with @Conditional, like this for example:

@Bean
@Conditional(ConfigNameCondition.class)
public SomeBean someBean() {
    return new SomeBean();
}

As shown in the javadoc for the nested condition annotations (linked to above) the nested conditions can be of any type. There's no need for them to all be of the same type as they are in this particular case.




回答2:


The annotations @ConditionalOnProperty and @ConditionalOnExpression both do NOT have the java.lang.annotation.Repeatable annotation so you would not be able to just add multiple annotations for checking multiple properties.

The following syntax has been tested and works:

Solution for Two Properties

@ConditionalOnExpression("${properties.first.property.enable:true} && ${properties.second.property.startServer:false}")

Note the following:

  • You need to using colon notation to indicate the default value of the property in the expression language statement
  • Each property is in a separate expression language block ${}
  • The && operator is used outside of the SpEL blocks

It allows for multiple properties that have differing values and can extend to multiple properties.

If you want to check more then 2 values and still maintain readability, you can use the concatenation operator between different conditions you are evaluating:

Solution for more then 2 properties

@ConditionalOnExpression("${properties.first.property.enable:true} " +
        "&& ${properties.second.property.enable:true} " +
        "&& ${properties.third.property.enable:true}")

The drawback is that you cannot use a matchIfMissing argument as you would be able to when using the @ConditionalOnProperty annotation so you will have to ensure that the properties are present in the .properties or YAML files for all your profiles/environments or just rely on the default value

Taken from here Spring Boot SpEL ConditionalOnExpression check multiple properties




回答3:


You can use an array of conditional value as:

@Configuration
public class MyConfigClass {

    @Bean
    @ConditionalOnProperty(prefix="test.configname", value = { "value1", "value2" })
    public MyBean myBean() {
        return new MyBean();
    }
}

This will create bean if property test.configname.value1 or test.configname.value2 exists, and value not false.

The Spring Boot Document has proper description for this.




回答4:


I am looking for configurationOnProperty usage where I can specify to consider more than one value

You can use Condition interface of Spring 4.0.

This interface has a method matches(...) which you can use.

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.type.AnnotatedTypeMetadata;

public class TestCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String testValue = (context.getEnvironment().getProperty("test.configname");
        return "value1".equalsIgnoreCase("testValue") || "value2".equalsIgnoreCase("testValue");
    }

}

And then use TestCondition inside your @Configuration like below :

@Configuration
public class TestConfig {

      @Conditional(value=TestCondition .class)
      public MyBean getTestConfigBean() {
          //TODO YOUR CODE;
      }

}

I would like to know if it is possible to specify confiugrationOnProperty with condition of havingValue != "value3"

public class TestCondition2 implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        String testValue = (context.getEnvironment().getProperty("test.configname");
        return ! "value3".equalsIgnoreCase("testValue");
    }

}

And then use it like this :

@Configuration
public class TestConfig {

      @Conditional(value=TestCondition2 .class)
      public MyBean getTestConfigBean() {
          //TODO YOUR CODE;
      }

}


来源:https://stackoverflow.com/questions/51257432/spring-conditionalonproperty-havingvalue-value1-or-value2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!