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

Spring Boot v2.7.6中抽象类引发的循环引用问题求助

解决方案:Spring Boot 2.7.6循环引用问题修复

问题根源

你的抽象类在@PostConstruct方法中通过ApplicationContext.getBean(this.getClass())获取自身实例,此时Bean尚未完成初始化流程,触发了Spring Boot 2.7.x更严格的循环依赖检测机制。


方案1:移除冗余的me字段(最优解)

代码中me.perform(request)完全等价于this.perform(request)——this本身就是子类实例,抽象方法perform会由子类实现。无需额外通过ApplicationContext获取自身,直接简化代码即可消除循环引用:

public abstract class AbstractTransactionalService<Request, Response, Exception> {

    public Response performService(final Request request, final Class<Exception> exceptionClass)
            throws Exception {
        try {
            final Response response = this.perform(request);
            return response;
        } catch (final Exception e) {
            // 保留原异常处理逻辑
            ...
        }
    }

    public abstract Response perform(Request request) throws Exception;
}

该方案彻底消除了循环引用触发点,代码更简洁,是优先选择的解决方案。


方案2:若需获取代理对象(如子类带@Transactional)

如果子类使用@Transactional等需要Spring代理的注解,直接用this调用perform会绕过代理(无法触发事务),此时可通过以下方式安全获取代理实例:

子方案2.1:通过@Autowired注入自身

Spring支持Bean自注入,直接在抽象类中注入自身实例,无需手动从ApplicationContext获取:

public abstract class AbstractTransactionalService<Request, Response, Exception> {

    @Autowired
    private AbstractTransactionalService<Request, Response, Exception> me;

    public Response performService(final Request request, final Class<Exception> exceptionClass)
            throws Exception {
        try {
            final Response response = this.me.perform(request);
            return response;
        } catch (final Exception e) {
            ...
        }
    }

    public abstract Response perform(Request request) throws Exception;
}

子方案2.2:监听上下文刷新事件

在Spring上下文完全初始化后再获取代理实例,避免初始化过程中的循环问题:

public abstract class AbstractTransactionalService<Request, Response, Exception> implements ApplicationListener<ContextRefreshedEvent> {

    @Autowired
    private ApplicationContext applicationContext;

    private AbstractTransactionalService<Request, Response, Exception> me;

    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        // 上下文完全刷新后再获取bean,避免重复执行可添加上下文判断
        if (event.getApplicationContext().getParent() == null) {
            me = applicationContext.getBean(this.getClass());
        }
    }

    public Response performService(final Request request, final Class<Exception> exceptionClass)
            throws Exception {
        try {
            final Response response = this.me.perform(request);
            return response;
        } catch (final Exception e) {
            ...
        }
    }

    public abstract Response perform(Request request) throws Exception;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 08:25:29