YAML 对象上的@ConditionalOnProperty

@ConditionalOnProperty on YAML objects

我有一个如下所示的 YAML:

client:
  auth:
    foo:
      something: 123
      whatever: 321
    bar:
      idk: 999
      anything: bleh

我正在尝试创建 bean,无论它们是否在该 YAML 上指定,例如:

@Bean
@ConditionalOnProperty(prefix = "client.auth", name = "foo")
public Foo foo() {
    return new Foo();
}

@Bean
@ConditionalOnProperty(prefix = "client.auth", name = "bar")
public Bar bar() {
    return new Bar();
}

这样的 YAML 应该只创建 Bar bean(没有指定 client.auth.foo):

client:
  auth:
    bar:
      idk: 999
      anything: bleh

但是,这不起作用(未创建 bean)。我还尝试了以下方法(为简洁起见省略了 foo - bar):

@Bean
@ConditionalOnProperty(prefix = "client.auth", value = "foo")
public Foo foo() {
    return new Foo();
}

@Bean
@ConditionalOnProperty(prefix = "client", name = "auth", havingValue = "foo")
public Foo foo() {
    return new Foo();
}

是否有可能实现我正在寻找的东西?怎么样?

方法 #1:

ConditionalOnProperty 处理完整的 属性 名称。对于您的用例,如果您可以添加一个额外的布尔参数,如 client.auth.foo.enabled,那么可能会起作用。如下图所示:

@Bean
@ConditionalOnProperty(value = "client.auth.foo.enabled", havingValue = "true")
public Foo foo() {
    return new Foo();
}

对应的yaml文件

client:
  auth:
    foo:
      enabled: true
      something: 123
      whatever: 321

方法 #2:

您可以实现自己的条件来检查 属性 前缀是否存在。

@Bean
@Conditional(MyCondition.class)
public Foo foo() {
    return new Foo();
}

static class MyCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        final String prefix = "client.auth.foo";
        if (context.getEnvironment() instanceof ConfigurableEnvironment env) {
            for (PropertySource<?> propertySource : env.getPropertySources()) {
                if (propertySource instanceof EnumerablePropertySource enumerablePropertySource) {
                    for (String key : enumerablePropertySource.getPropertyNames()) {
                        if (key.startsWith(prefix)) {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }
}

基于 针对您的用例进行了修改