【问题标题】:Spring Boot bean conditional on @ConfigurationProperties valueSpring Boot bean 以 @ConfigurationProperties 值为条件
【发布时间】:2018-08-15 15:45:31
【问题描述】:

Spring Boot 使用 @ConfigurationProperties 注解为我们提供了类型化的配置对象。优点之一是在使用 Spring Boot 注释处理器时可以免费在 IDE 中完成属性名称。另一个是:验证。

现在,我想让 bean 以属性的值为条件。实际上,我有两个接口实现,这个属性告诉我应该使用哪一个。我可以这样实现它:

ImplementationA.java

@Component
@ConditionalOnProperty(name = "foo.bar", havingValue = "a")
public class ImplementationA implements SomeInterface { ... }

ImplementationB.java

@Component
@ConditionalOnProperty(name = "foo.bar", havingValue = "b")
public class ImplementationB implements SomeInterface { ... }

application.yml

foo:
  bar: "a"

但是,我会失去类型化配置的优势。所以我想在@ConfigurationProperties 对象中声明这个属性:

FooProperties.java

@ConfigurationProperties(prefix = "foo")
public class FooProperties {

    private String bar;


    public String getBar() { ... }

    public void setBar(String bar) { ... }
}

这仍然有效,但是当我在此类中声明 bar 的默认值时,@ConditionalOnProperty 显然不会拾取它,因为此注释直接针对 Environment 操作(按设计)。所以也许最好不要混合这些概念。

所以问题是……

有没有办法让条件 bean 基于 @ConfigurationProperties 对象中的值?最好使用一些 @Conditional 注释而不创建 @Configuration bean,因为这意味着样板代码。

【问题讨论】:

  • @ConfigurationProperties 远低于@Conditional... 组件扫描链中的注释。因此,我认为这是不可能的。所有@Conditional 注释,如@Condition@ConditionalOnProperty@ConditionalOnExpression,都在@ConfigurationProperties 之前执行
  • 不能同时使用吗?像以前一样创建 FooProperties,但添加一个具有默认值的静态常量,并在 ConditionalOnProperty 的“havingValue”属性中引用它
  • 您找到问题的答案了吗?

标签: java spring spring-boot


【解决方案1】:

它可能没有那么性感,但一个潜在的解决方案可能是将您的配置自动装配到 SomeInterfaceConfiguration 中,该配置创建提供基于 FooProperties 的服务实现。

@Configuration
public class SomeInterfaceConfiguration {

    @Bean
    @Autowired
    public SomeInterface someInterface(FooProperties fooProperties){
        if("a".equals(fooProperties.getBar()){
            return SomeInterfaceImplementationA();
        } else {
            return SomeInterfaceImplementationB();
        }
    }
}

另一种选择是使用配置文件,但它与您想要的解决方案不同。 即有一个默认实现。

@Component
public class ImplementationA 

@Profile("b")
@Primary
@Component
public class ImplementationB

【讨论】:

    【解决方案2】:

    按照here 的建议,您可以像这样在@Conditional 中手动创建 ConfigurationProperties 对象:

    import org.springframework.boot.context.properties.bind.Binder
    ...
    YourConfigurationPropertiesClass config = Binder.get(context.getEnvironment())
    .bind("your.properties.prefix", YourConfigurationPropertiesClass.class).orElse(null);
    

    【讨论】:

      猜你喜欢
      • 2015-03-06
      • 1970-01-01
      • 2020-02-10
      • 2015-06-17
      • 2018-02-07
      • 2016-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多