You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring-context从5.3.9升级至5.3.13后出现循环依赖问题如何解决

问题根因

该报错本质是自引用循环依赖,结合Spring版本特性变更触发:

  • 代码结构本身存在循环:MyMessageHandler作为@Component需要注入内部@Bean方法声明的ThreadPoolTaskScheduler实例,而要执行@Bean方法创建ThreadPoolTaskScheduler实例,又需要先完成MyMessageHandler的实例化,二者形成依赖闭环。
  • 版本特性差异:org.springframework:spring-context从5.3.10版本开始收紧了循环依赖的默认处理规则,低版本中能自动兼容的自引用循环场景,高版本默认会直接抛出异常。

解决方案(按推荐优先级排序)

方案1:将@Bean方法迁移到独立配置类(最优)

@Bean声明本就不建议耦合在业务@Component类中,单独抽离到@Configuration配置类即可从根源打破循环:

@Configuration
public class ThreadPoolConfig {
    @Bean("MessageHandlerSchedulerInitializer")
    public ThreadPoolTaskScheduler messageHandlerSchedulerInitializer(){
        ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
        threadPoolTaskScheduler.setPoolSize(5);
        threadPoolTaskScheduler.setThreadNamePrefix("LmSolaceMessageHandler");
        return threadPoolTaskScheduler;
    }
}

调整后原来的MyMessageHandler类移除内部的messageHandlerSchedulerInitializer方法即可。

方案2:添加@Lazy注解延迟加载依赖

如果不想调整代码结构,可以在注入字段上添加@Lazy注解,触发依赖的延迟初始化:

@Component("myMessageHandler")
public class MyMessageHandler {

    @Autowired
    @Qualifier("MessageHandlerSchedulerInitializer")
    @Lazy // 新增该注解
    private ThreadPoolTaskScheduler messageHandlerScheduler;

    @Bean("MessageHandlerSchedulerInitializer")
    public ThreadPoolTaskScheduler messageHandlerSchedulerInitializer(){
        ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
        threadPoolTaskScheduler.setPoolSize(5);
        threadPoolTaskScheduler.setThreadNamePrefix("LmSolaceMessageHandler");
        return threadPoolTaskScheduler;
    }
}

原理是实例化MyMessageHandler时会先注入ThreadPoolTaskScheduler的代理对象,等第一次实际使用该线程池实例时才会触发真正的初始化,此时MyMessageHandler已经完成实例化,不会再触发循环。

方案3:全局开启允许循环引用(不推荐)

如果需要兼容历史代码不想做任何逻辑调整,可以在Spring配置中全局开启循环引用支持:

  • Spring Boot项目在application.properties中添加配置:
spring.main.allow-circular-references=true
  • 纯Spring项目可以在初始化上下文时配置:
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.setAllowCircularReferences(true);
context.register(YourConfig.class);
context.refresh();

该方案属于全局兜底兼容,可能会隐藏其他不合理的循环依赖设计,不建议长期使用。

内容的提问来源于stack exchange,提问作者Bhushan Phalak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 12:45:04