Spring Boot自定义Condition依赖已实例化Bean失败如何处理?
核心结论
你对Spring Condition的运行机制判断是正确的:
原生Spring的Condition校验发生在Bean定义注册阶段,早于所有业务Bean的实例化流程。此时容器中只存在各个Bean的定义信息,还没有完成任何常规Bean的实例化,所以不管你用dependsOn、@AutoConfigureAfter还是调整配置类加载顺序,都无法在matches方法中拿到已经实例化完成的myBean,这些排序配置的生效时机都晚于Condition校验的执行时机。
Condition本身设计的使用场景就是基于静态信息做校验:比如环境变量、配置属性、Bean定义元信息等,确实不支持依赖运行时已实例化的Bean做判断。
可行替代方案
如果确实需要基于已实例化的Bean属性决定是否创建目标Bean,可以用以下两种方案实现:
方案1:使用SmartInitializingSingleton手动注册Bean(通用Spring场景)
在所有单例Bean初始化完成后执行校验逻辑,符合条件就手动把目标Bean注册到容器中,代码示例如下:
@Configuration public class MyConfiguration implements ApplicationContextAware { private ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } @Bean public SmartInitializingSingleton conditionalRegisterMyClass() { return () -> { // 此时所有单例Bean已经完成初始化,可以直接获取 MyBeanType myBean = applicationContext.getBean("myBean", MyBeanType.class); if (myBean.getName().equals("Artem")) { DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) applicationContext.getAutowireCapableBeanFactory(); // 手动注册实例到Spring容器 beanFactory.registerSingleton("myClass", new MyClass()); } }; } }
这种方案不需要引入额外依赖,原生Spring即可支持,适配性最高。
方案2:使用Spring Boot提供的@ConditionalOnBean(Spring Boot场景)
Spring Boot扩展的条件注解@ConditionalOnBean会在Bean定义注册的后置阶段执行,只要将你的配置类调整为自动配置类,并且配置正确的加载顺序即可生效:
- 给
MyConfiguration加上注解:
@AutoConfiguration @AutoConfigureAfter({ConfigurationA.class, ConfigurationB.class}) public class MyConfiguration { @Bean @ConditionalOnBean(name = "myBean") // 可以结合自定义Condition实现属性校验,此时myBean已经可以正常获取 @Condition(MyCondition.class) public MyClass createMyClass() { return new MyClass(); } }
- 在
resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中添加MyConfiguration的全限定类名,让它走Spring Boot自动配置流程,此时@AutoConfigureAfter才会生效。
内容的提问来源于stack exchange,提问作者paul_oshea
相关产品推荐
相关产品推荐

