如何让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 { }
关键说明
- 空数组兼容:当配置文件中写
my.redis.connections: []时,environment.containsProperty("my.redis.connections")会返回true,条件匹配成功。 - 仅声明层级兼容:当配置文件中仅写
my.redis.connections:(无值无数组符号),通过遍历属性源键的方式可以检测到该层级存在,条件匹配成功。 - 原有逻辑保留:
@EnableMyRedis的开关逻辑不受影响,只有启用该注解后,才会进入AutoConfiguration的条件判断流程。
内容的提问来源于stack exchange,提问作者Emiya Elien
相关产品推荐
相关产品推荐

