当前位置: 首页 > news >正文

解决循环依赖报错问题

Caused by:
org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name ‘asyncTaskServiceImpl’: Bean with name
‘asyncTaskServiceImpl’ has been injected into other beans
[resignServiceImpl] in its raw version as part of a circular
reference, but has eventually been wrapped. This means that said other
beans do not use the final version of the bean. This is often the
result of over-eager type matching - consider using
‘getBeanNamesForType’ with the ‘allowEagerInit’ flag turned off, for
example.

at
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:649)
这个错误是由于 Spring 容器中的 循环依赖(circular dependency)问题引起的。asyncTaskServiceImpl 这个 bean 被注入到 resignServiceImpl 中时,出现了原始版本的 asyncTaskServiceImpl,而在最终完成创建时,它被包装过了,导致 resignServiceImpl 没有得到 asyncTaskServiceImpl 的最终版本。
详细分析

Spring 在处理依赖注入时,如果发现存在循环依赖,会尝试通过提前暴露一个原始对象(通常是代理对象)来解决循环引用问题。这时候,依赖的 bean 还没有完全创建完成,因此它会以 “原始” 版本暴露给依赖它的 bean,等到循环依赖关系解决后,Spring 会最终完成所有的 bean 初始化和代理包装。

但是,错误提示中指出,asyncTaskServiceImpl 被注入到 resignServiceImpl 中时是原始版本,而在依赖注入完成后,asyncTaskServiceImpl 被包装(通常是代理),这导致了 resignServiceImpl 使用了一个不完整或不期望的版本。最终的结果是,resignServiceImpl 并没有得到 asyncTaskServiceImpl 的最终版本。
可能的解决方法:
1. 使用 @Lazy 注解(使用这种方式就可以的)

可以使用 @Lazy 注解来延迟 asyncTaskServiceImpl 的初始化,避免在容器启动时过早创建 asyncTaskServiceImpl。

@Autowired
@Lazy
private AsyncTaskService asyncTaskServiceImpl;

这样 Spring 在注入时不会立即创建 asyncTaskServiceImpl,而是等到第一次使用时再创建,从而避免了循环依赖。
2. 避免构造函数注入中的循环依赖

如果是通过构造函数注入引起的循环依赖,可以考虑将注入方式改为字段注入(@Autowired)或 setter 注入。构造函数注入时,Spring 无法绕过循环依赖问题,而字段注入和 setter 注入会延迟创建对象,可能能够避免循环依赖。

// 将构造函数注入改为字段注入

@Autowired
private AsyncTaskService asyncTaskServiceImpl;

或者使用 setter 注入:

@Autowired
public void setAsyncTaskService(AsyncTaskService asyncTaskServiceImpl) {this.asyncTaskServiceImpl = asyncTaskServiceImpl;
}
  1. 使用 @PostConstruct 初始化

如果注入的服务之间有依赖关系,可以考虑在 @PostConstruct 方法中进行初始化,而不是通过构造函数或字段注入直接注入。

@PostConstruct
public void init() {// 在这里进行依赖注入的逻辑,避免循环依赖问题
}
  1. 使用 @Primary 和 @Qualifier 明确注入

如果有多个候选的 bean 可能导致依赖注入时的冲突,可以使用 @Primary 和 @Qualifier 注解明确指定哪个 bean 应该被注入。
5. 重构代码,避免循环依赖

循环依赖通常是设计上的问题。可以考虑重构代码,将部分依赖提取到不同的服务中,打破循环依赖。比如,使用事件机制、消息队列或者中介者模式来解耦服务之间的依赖关系。
6. 调整 @Bean 配置

如果是通过 @Configuration 类配置 bean,确保避免在同一类中直接引用互相依赖的 bean。可以使用 @Lazy 或调整配置方式来避免循环依赖。
总结:

这个错误的核心问题是循环依赖,导致在依赖注入时,某些 bean 被注入了未完成初始化的“原始版本”。可以通过延迟初始化(@Lazy)、使用 setter 注入或重构代码来打破循环依赖,解决这个问题。如果可能,最好重构服务的设计,以避免这种依赖关系。

http://www.lryc.cn/news/486683.html

相关文章:

  • 代码随想录第46期 单调栈
  • 中仕公考怎么样?事业编面试不去有影响吗?
  • OMV7 树莓派 tf卡安装
  • Go语言24小时极速学习教程(五)Go语言中的SpringMVC框架——Gin
  • 【汇编】c++游戏开发
  • Android Studio | 修改镜像地址为阿里云镜像地址,启动App
  • Rocky linux8 安装php8.0
  • Ubuntu 18 EDK2 环境编译
  • C语言项⽬实践-贪吃蛇
  • 智慧安防丨以科技之力,筑起防范人贩的铜墙铁壁
  • Spring:IoC/DI加载properties文件
  • Docker 篇-Docker 详细安装、了解和使用 Docker 核心功能(数据卷、自定义镜像 Dockerfile、网络)
  • 深挖C++赋值
  • 【免越狱】iOS砸壳 可下载AppStore任意版本 旧版本IPA下载
  • 【python笔记02】面向对象思想
  • Java基础-Java多线程机制
  • MySQL技巧之跨服务器数据查询:基础篇-A数据库与B数据库查询合并--封装到存储过程中
  • MATLAB向量元素的引用
  • leetcode-44-通配符匹配
  • 基于YOLOv8深度学习的智慧课堂学生专注度检测系统(PyQt5界面+数据集+训练代码)
  • vue项目使用eslint+prettier管理项目格式化
  • Java基础-组件及事件处理(中)
  • UNIX网络编程-TCP套接字编程(实战)
  • python编写一个自动清理三个月以前的邮件脚本
  • C++组合复用中,委托的含义与作用
  • 自制C++游戏头文件:C++自己的游戏头文件!!!(后续会更新)
  • java 读取 有时需要sc.nextLine();读取换行符 有时不需要sc.nextLine();读取换行符 详解
  • Redis知识分享(三)
  • python安装包报错
  • Linux性能优化之火焰图简介