首页 > 解决方案 > `@ConditionalOnProperty` 与多个 `@PropertySource` 一起使用

问题描述

我有一些 bean @ConditionalOnProperty,其中的属性来自一些@PropertySource. 但我有多个@PropertySources. 仅在其中之一中,将定义给定的条件属性。但令我惊讶的是,@ConditionalOnProperty注释会咨询每个属性源。并且由于属性不在每个属性源中,PropertyResolver因此会将 bean 标记为非数学。

我想要的是接口,具有实际实现和无操作实现,并控制将使用哪个实现。我不想使用配置文件来控制它,但配置文件是基于条件的,所以应该有办法。所以对我来说正在发生的事情是,我不考虑设置而没有实施。当然,我可以添加matchIfMissing,然后无论设置如何,我都会被排除在外。

注释是:

@ConditionalOnProperty(name = "feature.enabled", havingValue = "true")

在属性文件中是

feature.enabled=true

这里有什么问题?但实际上不可能,如果我使用@Conditional...我必须只使用一个属性源,对吗?

更新:具有以下 bean 定义,我有描述的行为:没有注册 bean,因为feature.enabled没有在application.properties. 添加matchIfMissing=true没有帮助,因为具有此参数的 bean 将始终添加,因为它(始终)不存在于application.properties. 添加@ConditionalOnMissingBean 也没有帮助我。我在 中设置feature.enabled为 true another.properties,但 FeatureImpl 被否决了,因为有属性源,其中 feature.enabled 不正确。令人惊讶的是,当时使用 @ConditionalOnMissingBean 注释的 FeatureNoOp 也没有注册。不知道为什么。

@Service
@Slf4j
@ConditionalOnProperty(name = "feature.enabled", havingValue = "false")
public class FeatureNoOp implements Feature {

对比

@Service
@Slf4j
@ConditionalOnProperty(name = "feature.enabled", havingValue = "true")
public class FeatureImpl implements Feature {

配置如下:

@Configuration
@PropertySource("classpath:application.properties")
public class Config {

    //...


    @Order(Ordered.HIGHEST_PRECEDENCE)
    @Configuration
    @PropertySource("classpath:another.properties")
    @Profile("war-deployment")
    public static class WarDeploymentConfig {
        //...
    }
}

标签: spring-boot

解决方案


正如 M.Deinum 正确建议的那样(谢谢!),真正的原因是在 @PropertySource 注释中。

我有 application.properties 的 @PropertySource,另外我有一些配置类,如下所示,只是为了带来另一个基于活动配置文件的属性源:

@Configuration
@PropertySource("classpath:profile-related-properties.properties")
@Profile("some-profile")
public static class SomeProfileConfig {}

即使这提供了一些明确的说明正在使用什么,它显然也说明了一些问题。我更改了代码,因此我不会“重复”声明 application.properties 的使用并重命名文件/配置文件,以便可以使用另一个自动发现的属性模式:application-{profile_name}.properties。在此更改之后,一切都按预期工作。


推荐阅读