您现在的位置是:网站首页 > 代码编程 > JAVA开发JAVA开发

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

不忘初心 不忘初心 2019-09-12 围观() 评论() 点赞() JAVA开发

简介:最近在项目中,用了@Async注解之后导致循环依赖报错,但是在我的印象中,spring是允许循环以来的,换句话说,spring自身是已经解决了循环依赖这个问题的,但是在这里竟然又出现了。详细信息如下,在注入bean的时候报错了:Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Err

最近在项目中,用了@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懒加载注解;

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

springboot

看完文章,有任何疑问,请加入群聊一起交流!!!

很赞哦! ()

文章评论

  • 请先说点什么
    人参与,条评论

请使用电脑浏览器访问本页面,使用手机浏览器访问本页面会导致下载文件异常!!!

雨落无影

关注上方公众号,回复关键字【下载】获取下载码

用完即删,每次下载需重新获取下载码

若出现下载不了的情况,请及时联系站长进行解决

站点信息

  • 网站程序:spring + freemarker
  • 主题模板:《今夕何夕》
  • 文章统计:篇文章
  • 标签管理标签云
  • 微信公众号:扫描二维码,关注我们