Spring 4.3.15+版本SchedulerFactoryBean注入及升级报错解决咨询
我帮你分析下这个Spring升级后遇到的BeanCurrentlyInCreationException报错问题,这个坑我之前也碰到过类似的,核心原因是**SchedulerFactoryBean还没完成初始化的时候,就有其他Bean急着去拿它的实例,导致getObject()返回了null**——Spring 4.3.16对Bean创建的生命周期检查比4.3.2严格了不少,所以之前隐藏的问题就暴露出来了。
下面是几种常见的触发场景和对应的解决办法:
1. 先排查是否存在循环依赖
如果你的业务Bean和SchedulerFactoryBean之间绕成了循环(比如业务Bean依赖Scheduler,而Scheduler的JobDetail又依赖这个业务Bean),升级后Spring的循环依赖处理逻辑收紧,就会直接报错。
- 解决思路:
- 别直接在JobDetail里注入业务Bean,改用
ApplicationContext动态获取:// 在你的Job类里这么写 @Autowired private ApplicationContext ctx; @Override public void execute(JobExecutionContext context) { YourBusinessBean bizBean = ctx.getBean(YourBusinessBean.class); // 执行业务逻辑 } - 或者给注入Scheduler的地方加
@Lazy注解,延迟它的初始化:@Autowired @Lazy private Scheduler scheduler;
- 别直接在JobDetail里注入业务Bean,改用
2. 检查SchedulerFactoryBean的自动启动配置
如果你的XML配置里给SchedulerFactoryBean开了autoStartup="true",它会在容器启动时立刻初始化,要是此时它依赖的其他Bean还没准备好,就会触发这个问题。
- 解决思路:
- 先关掉自动启动,手动控制启动时机:
<bean id="schedulerFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" autowire="byName"> <property name="autoStartup" value="false"/> <!-- 其他原有配置保持不变 --> </bean> - 然后在所有Bean初始化完成后,手动启动Scheduler:
@Autowired private SchedulerFactoryBean schedulerFactory; @PostConstruct public void initScheduler() { schedulerFactory.start(); }
- 先关掉自动启动,手动控制启动时机:
3. 别直接调用FactoryBean的getObject()方法
Spring 4.3.10+调整了FactoryBean的初始化逻辑,严格限制了getObject()的调用时机。如果你的代码里有直接调用schedulerFactory.getObject()的情况(而不是通过Spring容器注入Scheduler接口),肯定会踩这个坑。
- 解决思路:
- 老老实实通过Spring注入
Scheduler接口,别直接操作FactoryBean:// 正确姿势:注入Scheduler接口 @Autowired private Scheduler scheduler; // 错误姿势:直接调用FactoryBean的getObject(),赶紧改掉 // schedulerFactory.getObject();
- 老老实实通过Spring注入
4. 检查自定义的Bean处理器
如果项目里有自定义的BeanPostProcessor或者FactoryBean,它们可能在SchedulerFactoryBean初始化完成前就去获取实例,导致报错。
- 解决思路:
- 给自定义处理器设置最低优先级,让它等所有Bean都初始化完再执行:
@Order(Ordered.LOWEST_PRECEDENCE) public class YourCustomBeanPostProcessor implements BeanPostProcessor { // 你的处理器逻辑 }
- 给自定义处理器设置最低优先级,让它等所有Bean都初始化完再执行:
总结一下
这个问题本质就是Spring升级后对Bean创建的检查更严了,核心要避免的就是在SchedulerFactoryBean还没完全初始化好的时候就去拿它的实例。优先排查循环依赖和自动启动的配置,再结合上面的方法调整代码,应该就能解决问题了。
内容的提问来源于stack exchange,提问作者user66332

