@ConditionalOnProperty 就是根据 配置文件(application.properties 或 yml)中的开关 来决定是否加载某个组件。它是实现“功能开关”最常用的手段。


1. 核心逻辑

简单来说,它的逻辑是:“去配置文件里看一眼,如果那个配置项的值符合我的预期,我就启动;否则,我就当不存在。”


2. 常用属性解析

属性

说明

prefix

配置属性的前缀(可选)。

name / value

配置属性的完整名称(或配合 prefix 使用)。

havingValue

期待的值。只有配置项的值等于它时,才触发加载。默认为空字符串。

matchIfMissing

关键属性! 如果配置文件里压根没写这个 key,是否加载?true 表示加载,false(默认)表示不加载。


3. 实战场景:切换支付网关

假设你的系统支持“支付宝”和“微信”两种支付方式,你想通过配置文件灵活切换。

代码实现

@Configuration
public class PayConfiguration {

    @Bean
    @ConditionalOnProperty(prefix = "pay", name = "type", havingValue = "alipay")
    public PayService alipayService() {
        return new AlipayServiceImpl();
    }

    @Bean
    @ConditionalOnProperty(prefix = "pay", name = "type", havingValue = "wechat", matchIfMissing = true)
    public PayService wechatService() {
        return new WechatServiceImpl();
    }
}

配置文件效果:

  • 情况 A: pay.type=alipay -> 加载 alipayService

  • 情况 B: pay.type=wechat -> 加载 wechatService

  • 情况 C: 配置文件里什么都没写 -> 因为微信支付设置了 matchIfMissing = true,所以默认加载微信支付


4. 进阶技巧:如何判断“开启”或“关闭”?

很多时候我们只是想做一个功能开关(True/False)。

@Bean
@ConditionalOnProperty(name = "feature.message-log.enabled", havingValue = "true")
public MessageLogger messageLogger() {
    return new MessageLogger();
}
  • 如果 havingValue 没写,只要配置文件里该属性不为 false,都会匹配成功。

  • 注意:如果你填了 havingValue = "true",那么配置文件里写 enabled: true 才能生效。


5. 常见坑点

  1. 拼写错误: 这是最常见的,IDE 通常不会对字符串里的配置名做强校验。建议配合 additional-spring-configuration-metadata.json 使用以获得提示。

  2. 松散绑定(Relaxed Binding): Spring 支持横杠、下划线、驼峰互转。例如 my.feature-enabledmy.featureEnabled 在注解里通常都能匹配上,但建议保持风格统一。

  3. @Component 连用: 它不仅能用在 @Bean 方法上,也可以直接顶在 @Service@Component 类名上。


总结:两者的配合

在开发高级 Starter 时,通常会这样组合:

  1. 先用 @ConditionalOnProperty 检查用户是否开启了该功能。

  2. 再用 @ConditionalOnMissingBean 检查用户是否自定义了实现。

  3. 如果都满足,才加载默认的 Bean。