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 的最终版本。
可能的解决方法:
- 使用 @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;
}
- 使用 @PostConstruct 初始化
如果注入的服务之间有依赖关系,可以考虑在 @PostConstruct 方法中进行初始化,而不是通过构造函数或字段注入直接注入。
@PostConstruct
public void init() {
// 在这里进行依赖注入的逻辑,避免循环依赖问题
}
- 使用 @Primary 和 @Qualifier 明确注入
如果有多个候选的 bean 可能导致依赖注入时的冲突,可以使用 @Primary 和 @Qualifier 注解明确指定哪个 bean 应该被注入。
5. 重构代码,避免循环依赖
循环依赖通常是设计上的问题。可以考虑重构代码,将部分依赖提取到不同的服务中,打破循环依赖。比如,使用事件机制、消息队列或者中介者模式来解耦服务之间的依赖关系。
6. 调整 @Bean 配置
如果你是通过 @Configuration 类配置 bean,确保避免在同一类中直接引用互相依赖的 bean。你可以使用 @Lazy 或调整配置方式来避免循环依赖。
总结:
这个错误的核心问题是循环依赖,导致在依赖注入时,某些 bean 被注入了未完成初始化的“原始版本”。你可以通过延迟初始化(@Lazy)、使用 setter 注入或重构代码来打破循环依赖,解决这个问题。如果可能,最好重构服务的设计,以避免这种依赖关系。