spring 循环依赖,Bean使用@Async注解 导致项目启动失败

2022年7月18日11:17:14

  一天下午,重新部署测试环境的时候,发现服务启动失败,报如下错误:

ERROR o.s.web.context.ContextLoader - Context initialization failed
  org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'matchAutoJiaoJuan': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.online.tk.test.service.MatchService com.online.tk.test.task.matchAutoJiaoJuan.matchService; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'matchService': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.online.tk.test.service.testAnswerCardService com.online.tk.test.service.MatchService.testAnswerCardService; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'testAnswerCardService': Bean with name 'testAnswerCardService' has been injected into other beans [practiceCardDubboService] 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

大致的意思是  :启动失败,创建bean失败,名为“testanswercardService”的bean已作为循环引用的一部分,以其原始版本注入到其他bean[practicecardDuboService]中,但最终被包装。这意味着其他bean不使用bean的最终版本。这通常是过度渴望类型匹配的结果-例如,考虑在禁用“allowagerinit”标志的情况下使用“getBeannameSoftype”(Injection 注射  Autowired自动装配;注解; nested 嵌套的)

简单来说,项目中存在了循环引用。matchService 中注入了testAnswerCardService ,同时在testAnswerCardService 中也引用了

matchService ,导致循环引用。因为是老项目中,确实存在着循环引用的问题,关于循环引用如何解决,稍后总结。

循环引用这个问题不是最近开发的功能,是一直存在的,为什么今天突然有问题了?

一,首先怀疑测试环境代码的有问题,对比了下没有发现什么区别。然后部署了别的分支(match和dev)分支的代码,发现报同样的问题,初步判定不是代码的问题(后来结果证明这个判断是错的,忽略了小小的一个字段)

二,然后猜测是不是spring什么相关版本自动升级了,看了看pom文件的结构,都是定义的特别的某个的版本,目前老项目使用的是4.2.5,检查了一遍,也没发现其他异常,排除版本突然升级的问题

三,是不是测试环境在搞什么测试动作,重新启动了下其他的两个项目,发现是没问题的,??尴尬了。

四,是不是还是代码的问题呢

     节前刚上线,那个时候代码还是没有问题的。重新拉了一个分支,然后将代码会滚到节前,竟然发现代码是否运行的。所以应该还是代码的问题??,接着试着将代码还原到昨天,发现代码仍然没有问题。逐步缩小范围,然后git compare,发现了如下代码:

哈哈,在testAnswerCardService 类里面,有一个异步方法。

四,虽然找到了原因,但是不理解原理,找了找相关资料

 原因解释如下:在程序启动的时候,Spring 已经对testAnswerCardService 里面的matchService记载完成,当准备创建matchService的时候发现使用了@Async注解,即Spring又需要江Bean代理一次,然后Spring发现该Bean已经被其他对象注入,所以会造成这个问题。

关于@Async生成代理这块,其实还是有些模糊,参考一下文章:

https://blog.csdn.net/lianhuazy167/article/details/66967673

小结

      回想这个排查思路,其实挺简单的,但是不够仔细,导致绕了远路。又对spring这一块了解了下,并且对于项目中的整个pom文件结构做了了解,也算学习和提升下,不断进步吧。

  • 作者:追梦的晓米
  • 原文链接:https://blog.csdn.net/u013034640/article/details/90033554
    更新时间:2022年7月18日11:17:14 ,共 2468 字。