Spring Boot中@ConditionalOnProperty正则前缀匹配的正确实现
解决Spring Boot中基于数组格式属性启用配置类的问题
首先明确:@ConditionalOnProperty的prefix参数不支持正则表达式,它仅用于指定固定的属性前缀,所以你用^sites\[.*\].*这种写法肯定不会生效。下面给你几个实用的解决方案:
方案一:自定义Condition类(精准控制判断逻辑)
自己实现Spring的Condition接口,通过Environment遍历所有属性键,匹配sites[数字].id这种格式的属性。
代码实现
- 编写自定义Condition:
import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; import org.springframework.core.env.Environment; import java.util.regex.Pattern; public class OnSitesIdExistsCondition implements Condition { // 匹配sites[0].id、sites[1].id这类格式的正则 private static final Pattern SITE_ID_PATTERN = Pattern.compile("^sites\\[\\d+\\]\\.id$"); @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { Environment env = context.getEnvironment(); // 遍历所有属性键,找到匹配的就返回true for (String propName : env.getPropertyNames()) { if (SITE_ID_PATTERN.matcher(propName).matches()) { return true; } } return false; } }
- 在配置类上使用该Condition:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; @Configuration @Conditional(OnSitesIdExistsCondition.class) public class TestConfiguration { @Bean public TestManager testManager() { return new TestManager(); } }
方案二:使用@ConditionalOnExpression(更简洁)
不想写自定义类的话,直接用@ConditionalOnExpression结合SpEL表达式,一行代码完成判断:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ConditionalOnExpression; import org.springframework.context.annotation.Configuration; @Configuration // 用SpEL遍历所有属性,匹配目标格式 @ConditionalOnExpression("#{environment.getPropertyNames().stream().anyMatch(name -> name matches '^sites\\[\\d+\\]\\.id$')}") public class TestConfiguration { @Bean public TestManager testManager() { return new TestManager(); } }
这个方案代码量少,适合不需要额外逻辑的简单场景。
方案三:结合@ConfigurationProperties(适合需使用属性内容的场景)
如果你的sites是数组/列表结构,后续还要用到这些属性值,可以先通过@ConfigurationProperties绑定属性,再判断是否存在有效的id字段:
代码实现
- 定义属性绑定类:
import org.springframework.boot.context.properties.ConfigurationProperties; import java.util.List; @ConfigurationProperties(prefix = "sites") public class SiteProperties { private List<Site> list; public static class Site { private String id; // 必须添加getter和setter public String getId() { return id; } public void setId(String id) { this.id = id; } } public List<Site> getList() { return list; } public void setList(List<Site> list) { this.list = list; } }
- 在配置类中使用:
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; @Configuration @EnableConfigurationProperties(SiteProperties.class) public class TestConfiguration { @Bean @Conditional(OnValidSiteCondition.class) public TestManager testManager(SiteProperties siteProperties) { // 可直接使用siteProperties中的属性内容 return new TestManager(); } // 内部类实现Condition,判断是否存在带有效id的site static class OnValidSiteCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { SiteProperties props = context.getBeanFactory().getBean(SiteProperties.class); return props.getList() != null && !props.getList().isEmpty() && props.getList().stream().anyMatch(site -> site.getId() != null); } } }
这个方案不仅能判断属性是否存在,还能验证属性有效性,适合需要操作这些属性的场景。
内容的提问来源于stack exchange,提问作者Abhilash
相关产品推荐
相关产品推荐

