Spring中如何结合@ConfigurationProperties与@Conditional使用?
结合@ConfigurationProperties与@Conditional实现条件化Bean的解决方案
你之前的方案失败的核心原因是:Condition接口的matches方法执行时机早于@ConfigurationProperties注解的Bean初始化流程,此时BeanFactory中还未创建ClientProperties实例,直接调用getBean自然会找不到。
下面提供两种可行的解决方案,既保留@ConfigurationProperties的强类型与重构优势,又实现条件化Bean:
方案一:在自定义Condition中手动绑定属性到Properties类
通过Spring的Binder工具,直接从Environment中读取属性并绑定到ClientProperties实例,无需依赖已初始化的Bean:
- 定义带常量前缀的
ClientProperties类:
@ConfigurationProperties(prefix = ClientProperties.PREFIX) public class ClientProperties { public static final String PREFIX = "client"; private boolean secured; public boolean isSecured() { return secured; } public void setSecured(boolean secured) { this.secured = secured; } }
- 修改自定义Condition实现:
public class SecurityEnabledCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { ClientProperties props = new ClientProperties(); // 从Environment绑定属性到实例 Binder.get(context.getEnvironment()) .bind(ClientProperties.PREFIX, Bindable.ofInstance(props)); return props.isSecured(); } }
- 在配置类中使用该Condition,同时确保
ClientProperties可被扫描为Bean(如果需要作为Bean使用):
@Configuration @ConfigurationPropertiesScan // 扫描@ConfigurationProperties注解的类 public class SecurityConfig { @Conditional(SecurityEnabledCondition.class) @Bean public SecurityBean securityBean() { return new SecurityBean(); } }
方案二:使用@ConditionalOnExpression直接引用Properties Bean属性(更简洁)
无需自定义Condition,直接通过Spring Boot的表达式条件绑定ClientProperties的属性:
- 确保
ClientProperties被注册为Bean,可通过@EnableConfigurationProperties或@ConfigurationPropertiesScan实现:
@Configuration @EnableConfigurationProperties(ClientProperties.class) public class SecurityConfig { @Bean // 通过spel表达式直接引用ClientProperties的属性 @ConditionalOnExpression("#{clientProperties.secured}") public SecurityBean securityBean() { return new SecurityBean(); } }
这里的clientProperties是Spring自动生成的Bean名称(类名首字母小写),若需自定义名称,可在ClientProperties上添加@Component("customName")或通过@Bean方法指定。
这种方式完全依托@ConfigurationProperties的强类型特性,重构时只需修改ClientProperties的属性名,同步调整spel表达式中的对应字段即可,无需接触原始配置键名。
内容的提问来源于stack exchange,提问作者Tuomas Toivonen
相关产品推荐
相关产品推荐

