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

升级Spring Boot 2.7.18后如何解决A→B→C→A循环依赖问题?

解决Spring Boot 2.7.18升级后的循环依赖问题

先修正接口解耦的错误

你之前让SessionCreateInterceptor实现SessionManager属于职责错位——它的核心功能是请求拦截,而非会话池管理,这直接导致Spring容器中出现两个SessionManager实现类(SessionPool和SessionCreateInterceptor),引发多Bean冲突。

修正步骤:

  • 仅保留SessionPool实现SessionManager接口
  • SessionCreateInterceptor改为依赖SessionManager,而非实现它

修正后的SessionCreateInterceptor注入示例:

@Component
@Scope("prototype")
public class SessionCreateInterceptor extends AbstractSessionInterceptor {
    private final SessionManager sessionManager;

    // 构造器注入SessionManager
    public SessionCreateInterceptor(SessionManager sessionManager) {
        this.sessionManager = sessionManager;
    }

    // 原业务逻辑中用到SessionPool的地方,改为调用sessionManager的方法
}

拆解A→B→C→A的循环依赖

针对SessionPool→SessionCreateWrapper→SessionCreateInterceptor→SessionPool的循环链,可通过以下方式打破:

方案1:使用@Lazy延迟注入

在循环依赖的任意一端添加@Lazy注解,让Spring延迟初始化依赖Bean,规避启动时的循环检测:

比如在SessionCreateWrapper的构造器注入中添加@Lazy:

@Controller
@Scope("prototype")
public class SessionCreateWrapper extends WebServiceGatewaySupport {
    private final SessionManager sessionManager;

    public SessionCreateWrapper(@Lazy SessionManager sessionManager) {
        this.sessionManager = sessionManager;
    }
}

或者在SessionPool依赖SessionCreateWrapper的地方添加@Lazy:

@Service
public class SessionPool implements SessionManager {
    private final SessionCreateWrapper sessionCreateWrapper;

    public SessionPool(@Lazy SessionCreateWrapper sessionCreateWrapper) {
        this.sessionCreateWrapper = sessionCreateWrapper;
    }
}

方案2:重构职责边界

循环依赖往往是职责不清晰的信号,可拆分核心逻辑打破循环:

  1. 让SessionPool只负责会话的存储、获取(单一职责),移除它对SessionCreateWrapper的直接依赖
  2. 新增会话创建服务类(比如SessionCreator),专门处理会话创建逻辑,由它依赖SessionCreateWrapper和SessionManager
  3. SessionCreateInterceptor需要创建会话时,调用SessionCreator而非直接依赖SessionPool

示例结构:

// 新增会话创建服务
@Service
public class SessionCreator {
    private final SessionCreateWrapper sessionCreateWrapper;
    private final SessionManager sessionManager;

    public SessionCreator(SessionCreateWrapper sessionCreateWrapper, SessionManager sessionManager) {
        this.sessionCreateWrapper = sessionCreateWrapper;
        this.sessionManager = sessionManager;
    }

    public Security createAndStoreSession(SharedContext context) {
        Security session = sessionCreateWrapper.createSession();
        sessionManager.addToPool(session);
        return session;
    }
}

原循环链会被打破:SessionPool不再依赖SessionCreateWrapper,SessionCreateInterceptor依赖SessionCreator,SessionCreator依赖SessionCreateWrapper和SessionManager。

方案3:使用Provider延迟获取Bean

如果不想大幅修改代码,可通过org.springframework.beans.factory.ObjectProvider延迟获取依赖Bean,避免循环:

比如在SessionPool中使用ObjectProvider:

@Service
public class SessionPool implements SessionManager {
    private final ObjectProvider<SessionCreateWrapper> sessionCreateWrapperProvider;

    public SessionPool(ObjectProvider<SessionCreateWrapper> sessionCreateWrapperProvider) {
        this.sessionCreateWrapperProvider = sessionCreateWrapperProvider;
    }

    // 需要使用SessionCreateWrapper时再获取实例
    public void someMethod() {
        SessionCreateWrapper wrapper = sessionCreateWrapperProvider.getObject();
        // 业务逻辑
    }
}

关于setter注入的补充

你之前尝试setter注入仍报错,大概率是循环链中还有其他Bean(比如WorkflowTrigger)参与了循环,需要确保所有循环依赖的节点都使用setter注入,或结合@Lazy一起使用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 06:33:13