You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Spring @ConditionalOnProperty检测属性是否存在(无值也可)

解决方案:自定义属性层级存在性判断条件

默认的@ConditionalOnProperty仅检查属性是否有有效值,无法识别空数组、仅声明层级的属性(如my.redis.connections:)。要实现“只要属性层级存在就加载配置”的需求,需要自定义Condition来完成判断。

步骤1:自定义Condition实现

编写一个Condition类,直接从Environment中检查目标属性层级是否存在,无论其值是否为空:

import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.AbstractEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.type.AnnotatedTypeMetadata;
import org.springframework.util.StringUtils;

import java.util.Map;

public class OnPropertyHierarchyPresentCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        // 读取自定义注解的prefix参数
        Map<String, Object> attributes = metadata.getAnnotationAttributes(ConditionalOnPropertyHierarchy.class.getName());
        if (attributes == null) {
            return false;
        }
        String prefix = (String) attributes.get("prefix");
        if (StringUtils.isEmpty(prefix)) {
            return false;
        }

        // 检查环境中是否存在目标属性层级
        AbstractEnvironment environment = (AbstractEnvironment) context.getEnvironment();
        // 情况1:直接检查属性是否存在(包括空数组)
        if (environment.containsProperty(prefix)) {
            return true;
        }

        // 情况2:遍历所有属性源,检查是否存在以prefix开头的键(处理仅声明层级无值的情况)
        for (PropertySource<?> source : environment.getPropertySources()) {
            if (source instanceof MapPropertySource mapSource) {
                for (String key : mapSource.getSource().keySet()) {
                    if (key.equals(prefix) || key.startsWith(prefix + ".")) {
                        return true;
                    }
                }
            }
        }
        return false;
    }
}

步骤2:自定义注解绑定Condition

创建一个自定义注解,方便在配置类上使用该条件:

import org.springframework.context.annotation.Conditional;

import java.lang.annotation.*;

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnPropertyHierarchyPresentCondition.class)
public @interface ConditionalOnPropertyHierarchy {
    // 指定要检查的属性前缀/层级
    String prefix();
}

步骤3:修改自动配置类

将自定义注解替换原有的条件注解,应用到AutoConfiguration上:

@ConditionalOnPropertyHierarchy(prefix = "my.redis.connections")
@Import(PropertyBeanDefinitionRegistrar.class)
public class AutoConfiguration {

}

关键说明

  1. 空数组兼容:当配置文件中写my.redis.connections: []时,environment.containsProperty("my.redis.connections")会返回true,条件匹配成功。
  2. 仅声明层级兼容:当配置文件中仅写my.redis.connections:(无值无数组符号),通过遍历属性源键的方式可以检测到该层级存在,条件匹配成功。
  3. 原有逻辑保留:@EnableMyRedis的开关逻辑不受影响,只有启用该注解后,才会进入AutoConfiguration的条件判断流程。

内容的提问来源于stack exchange,提问作者Emiya Elien

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 17:55:01