你们好,我是金金金。
场景
- 启动服务时,报错:应用程序上下文中的某些bean的依赖关系形成了一个循环
循环依赖
依赖循环指的是两个或多个类之间相互依赖的情况,即类A依赖类B,同时类B也依赖类A。 这种情况会导致编译器无法确定类的加载顺序,从而产生编译错误
- 如上图:
BeanA
类依赖了BeanB
类,同时BeanB
类又依赖了BeanA
类。这种依赖关系形成了一个闭环,这种依赖关系就称之为循环依赖
排查
从报错信息可以得知,这是一个依赖循环的问题~,问题出在
MqConfig
和rabbitTemplateConfigurer
这两者形成了相互依赖,从而产生了依赖循环
- 从报错得知,整理的依赖顺序如下~
payController
依赖于payOrderServiceImpl
payOrderServiceImpl
依赖于MqConfig
MqConfig
依赖于rabbitTemplate
rabbitTemplate
依赖于rabbitTemplateConfigurer
rabbitTemplateConfigurer
依赖于MqConfig
- 好,一步步来,走起~
-
我先贴出
MqConfig
和RabbitMqHelper
代码Mq.config.java
RabbitMqHelper.java
-
从报错开始排查,首先看
PayController
,这里面使用了IPayOrderService
那必然有依赖关系 -
再继续看
payOrderServiceImpl
- PayOrderServiceImpl里面使用到了rabbitMqHelper,而rabbitMqHelper又是在MqConfig里面注册为一个Bean的,所以也就是为什么payOrderServiceImpl依赖于MqConfig的原因了~
-
继续走,我们看一下
MqConfig
,其实上面也有贴出MqConfig
的详细代码了,我这里再放一遍- 从报错显示,
MqConfig
依赖于rabbitTemplate
,这很明显了,因为我MqConfig
里面有使用到rabbitTemplate
,所以也存在着依赖关系
- 从报错显示,
-
继续,我们可以看到
rabbitTemplate
依赖于rabbitTemplateConfigurer
,这里得看一下源码了,跟着节奏,走起-
我们来到
RabbitAutoConfiguration
里面,可以看到三个内部类 -
根据报错得知
rabbitTemplate
依赖于rabbitTemplateConfigurer
,来看下RabbitTemplateConfiguration
这个内部类究竟是什么?- 现在就很明显了,可以看到
rabbitTemplate
就在RabbitTemplateConfiguration
内部类当中,rabbitTemplate
在这个内部类当中注册为了Bean
,而且这个Bean
是依赖于RabbitTemplateConfigurer
的,所以也就是为什么rabbitTemplate
依赖于rabbitTemplateConfigurer
- 现在就很明显了,可以看到
-
-
好,现在也就是最后一点,
rabbitTemplateConfigurer
为什么又依赖于MqConfig
呢,这两者导致了依赖循环
-
首先看下
rabbitTemplateConfigurer
方法,从源码可以得知 参数里面需要一个ObjectProvider messageConverter
消息转换器 -
我在
MqConfig
里面 也自定义了一个消息转换器,问题就出在这里
造成error的原因
MqConfig
依赖于rabbitTemplate
rabbitTemplate
的自动注入需要有MessageConverter
而我又在MqConfig
自定义了MessageConverter
MqConfig
需要rabbitTemplate
,由于我定义了消息转换器,而rabbitTemplate
又会使用到MqConfig
,
反反复复,就形成了循环依赖
解决
- 知道了错误的原因,解决起来就很简单了,就是因为
MqConfig
需要rabbitTemplate
,由于我定义了消息转换器,而rabbitTemplate
又会使用到MqConfig
这个问题所导致循环依赖。
第一种解决方案
-
把消息转换器放到别的配置类中去,这样就可以避免
rabbitTemplate
去找MqConfig
第二种解决方案
-
要么就把
MqConfig
类中的rabbitTemplate
以及init
方法拿走,直接切断关系使MqConfig
不依赖于rabbitTemplate
,我选择放在我的RabbitMqHelper
类当中
测试
-
完美启动,不报错了~
总结
依赖循环导致的问题,切断两者互相依赖关系即可~
- 编写有误还请大佬指正,万分感谢。