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
相关产品推荐
相关产品推荐

