首页   >   代码编程   >   JAVA开发

SpringBoot使用@Async注解导致循环依赖的原因及解决方案

最近在项目中,用了@Async注解之后导致循环依赖报错,但是在我的印象中,spring是允许循环以来的,换句话说,spring自身是已经解决了循环依赖这个问题的,但是在这里竟然又出现了。

详细信息如下,在注入bean的时候报错了:

Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'personalService': Bean with name 'personalService' has been injected into other beans [groupService,userServiceImpl] 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 'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:605)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:273)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1239)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1166)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:593)
	... 79 common frames omitted

开始一直去找循环依赖,导致耽误了很多时间,后来确认代码就是加了异步注解之后,顺着@Async注解这个方向去查找问题,最终定位到原因:注入bean的时候,直接调用了自身,而没有调用自身的代理类

问题产生的原因,spring循环依赖注入原理:

查问题的时候,找到一篇大佬写的文章,讲述的特别详细:https://blog.csdn.net/lianhuazy167/article/details/66967673,摘抄部分核心文字过来,以让大家更好的理解。

步骤1:A依赖B、C依赖B,B依赖C,并且B实现类的方法上存在@async注解,即B在实例化完成前会生成代理。

步骤2:A开始create,发现B未实例化,于是先cache A。

步骤3:B开始create,发现C未实例化,于是先cache B。

步骤4:C开始create,发现B已实例化,取出cache的B,注入C中,C finish。

(为什么B未实例化完就注入到C中了?that is not fully initialized yet - a consequence of a circular reference,因为存在循环依赖,所以允许先注入。猜测未做是否被代理的检测)

步骤5:生成B的代理类B@108e。

步骤6:B@108e注入到A时,发现B@108e的原始实例B已注入到循环引用的C中,却没有使用B的最终代理类B@108e,所以抛异常。

上述几个步骤,如果大家按顺序仔细推敲一下,就能大概明白问题的所在了,其实总的来说,跟以前碰见的事务注解不生效的问题差不多,都是代理没有被正确注入导致,讲真,我感觉提示“多个bean注入失败”更贴近。。。

解决方案:

1、重新建个类,将用@Async注解的方法都移出去放在此类中,再将新建的类注入进去;

2、在@Autowired注解上加上@Lazy懒加载注解;

上述两个方法二选一!!!

QQ群: 686430774  /  718410762

站长Q: 1347384268

如果文章有帮到你,可以考虑请博主喝杯咖啡!

分享到:

欢迎分享本文,转载请注明出处!

作者:不忘初心

发布时间:2019-09-12

永久地址:https://www.jiweichengzhu.com/article/fad4cb7f5dfd4639954f717443fe7018

评论