Spring Boot中如何基于配置列表值使用Conditional接口解决加载时序问题
问题根本原因
Spring中Condition的执行时机是Bean定义注册阶段,这个阶段所有Bean的实例化、属性注入、初始化操作都还没执行,所以你在自定义AwsCondition中通过@Autowired注入MyTestData必然会拿到null,这是Spring容器的生命周期规则决定的,和代码写法错误无关。
解决方案(按推荐度排序)
方案1:直接在Condition中读取配置(最推荐)
无需依赖MyTestData Bean,直接通过ConditionContext获取环境变量,手动读取YAML中的配置,完全匹配Condition的执行逻辑:
@Configuration public class AwsCondition implements Condition { @Override public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { log.info("inside...........condition"); // Spring Boot 2.x+ 可以用Binder直接把配置绑定为MyTestData对象,无需等待Bean初始化 MyTestData data = Binder.get(context.getEnvironment()) // 替换为你@ConfigurationProperties配置的前缀,没有前缀则填空字符串 .bind("your-config-prefix", MyTestData.class) .orElse(null); return data != null && data.getListeners().size() > 1; } }
如果判断逻辑简单,也可以直接读取配置值判断:
context.getEnvironment().getProperty("your-config-prefix.listeners.size", Integer.class),不用做对象绑定。
方案2:改为@Bean方式注册组件,在Bean创建阶段判断
如果一定要复用MyTestData已经写好的初始化校验逻辑,可以把TestS3ListenerRouter的注册改为@Bean方式:
@Configuration public class RouterConfig { @Bean public TestS3ListenerRouter testS3ListenerRouter(MyTestData data) { // 此时MyTestData已经完成注入和初始化,可以直接拿到配置值判断 if (data.getListeners().size() > 1) { return new TestS3ListenerRouter(); } // 不符合条件返回null,Spring不会注册该Bean return null; } }
同时删除TestS3ListenerRouter类上的@Component和@Conditional(AwsCondition.class)注解即可。
方案3:直接用Spring自带条件注解(逻辑简单时优先选择)
如果只是要判断listeners数量大于1,无需自定义Condition,直接用@ConditionalOnProperty即可:
@Component // 判断配置中第二个listener是否存在,等价于size>=2 @ConditionalOnProperty(prefix = "your-config-prefix", name = "listeners[1]", matchIfMissing = false) public class TestS3ListenerRouter extends RouteBuilder { // 原有逻辑不变 }
这种方式代码量最少,无需额外维护自定义Condition类。
内容的提问来源于stack exchange,提问作者JDGuide
相关产品推荐
相关产品推荐

