Spring @ConditionalOnProperty 的属性值为"value1"或"value2"时生效。

32

我正在寻找 configurationOnProperty 的使用方法,其中我可以指定考虑多个值,如下所示

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

或者

我想知道是否可以指定 confiugrationOnProperty 具备条件 havingValue != "value3"

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

请告诉我是否有一种方法可以在 spring boot 配置中实现上述任何一种情况。


4个回答

41

Spring Boot提供了 AnyNestedCondition,用于创建条件,当任何嵌套条件匹配时将进行匹配。它还提供了 AllNestedConditionsNoneNestedConditions,分别用于匹配所有嵌套条件或不匹配任何嵌套条件的情况。

对于您想要匹配 value1value2 值的特定情况,您可以像这样创建一个 AnyNestedCondition

class ConfigNameCondition extends AnyNestedCondition {

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

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

    }

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

    }

}

然后像这样使用@Conditional

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

如上面链接的嵌套条件注释(javadoc)所示,嵌套条件可以是任何类型。它们不需要像这种情况一样都是相同的类型。


6
看起来很糟糕。你有办法让 @ConditionalOnProperty 可以重复使用吗? - gstackoverflow
1
返回已翻译的文本:是的。虽然实现起来并不容易,因为有些人想要AND语义,而另一些人则想要OR。嵌套条件可能并不美观,但 AnyNestedConditionAllNestedConditionsNoneNestedConditions 会给您带来很多灵活性。 - Andy Wilkinson
1
它很灵活,但不够用户友好。 - gstackoverflow
您对@Qualifier使用相同的逻辑(AND),这样每个人都很满意。 - gstackoverflow
3
我所链接的问题尚未被拒绝,如果您阅读它,您会发现需要对Spring Framework进行更改。与其发表一系列贬低性言论,也许您想做些有建设性的事情并贡献一些拉取请求? - Andy Wilkinson
显示剩余4条评论

18

注释@ConditionalOnProperty@ConditionalOnExpression都没有java.lang.annotation.Repeatable注释,因此您无法仅添加多个注释以检查多个属性。

已测试并且可以工作的语法如下:

两个属性的解决方案

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

请注意以下内容:

  • 您需要使用冒号表示法来指示表达式语言语句中属性的默认值
  • 每个属性都在单独的表达式语言块${}中
  • &&运算符用于SpEL块之外

它允许具有不同值并且可以扩展到多个属性的多个属性。

如果您想要检查多于2个值并仍然保持可读性,则可以在您正在评估的不同条件之间使用连接运算符:

超过2个属性的解决方案

@ConditionalOnExpression("${properties.first.property.enable:true} " +
        "&& ${properties.second.property.enable:true} " +
        "&& ${properties.third.property.enable:true}")
缺点是您无法像使用@ConditionalOnProperty注释时那样使用matchIfMissing参数,因此您必须确保属性存在于所有配置文件(.propertiesYAML)中的所有配置文件/环境中,或者只依靠默认值。
取自此处:Spring Boot SpEL ConditionalOnExpression check multiple properties

6
我正在寻找使用configurationOnProperty的方法,可以指定考虑多个值。
您可以使用Spring 4.0Condition接口
此接口有一个可以使用的matches(...)方法。
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");
    }

}

然后在你的@Configuration中像下面这样使用TestCondition

@Configuration
public class TestConfig {

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

}

我想知道是否可以在配置属性中指定条件,使其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");
    }

}

然后像这样使用它:
@Configuration
public class TestConfig {

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

}

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接