Spring 出现循环依赖 (Is there an unresolvable circular reference?) 哪种解决方式最好?

2020-05-21 08:19:33 +08:00
 linuxsteam

问题出现场景: 本地启动不会报错,服务器上启动会报错 Error creating bean with name ‘passwordEncoder’: Requested bean is currently in creation: Is there an unresolvable circular reference?

图 1 图 2 图 3

请问

5812 次点击
所在节点    Java
20 条回复
SoulSleep
2020-05-21 08:31:46 +08:00
现在版本的 Spring 不会在日志里打印出你循环依赖的三个类吗?

如果你本地启动没问题,那大概就是加载顺序的问题了

循环依赖我感觉有两种办法:


1.检查你的引用是否有 jar 冲突,jar 的加载顺序改变了 bean 初始化的顺序
2.使用 @DependOn 去指定 bean 加载顺序
Dachunlv
2020-05-21 08:36:42 +08:00
出现循环依赖大多数情况说明逻辑设计上就出了问题,可以尝试调整设计本身,否则治标不治本。比如创建中间代理 Bean ?
luckyrayyy
2020-05-21 08:39:01 +08:00
懒加载一个
luckyrayyy
2020-05-21 08:41:53 +08:00
或者你只从一个地方注入,另一个地方把已经注入的 bean 以构造器参数 /setter 的方式传过去
xuanbg
2020-05-21 08:43:38 +08:00
循环依赖就是典型的「代码写错了地方」。解决这个问题也很简单,把写错地方的代码挪到正确的地方就行。如楼主的例子,就是把 passwordEncode 这个方法从 WebSecurityConfig 拿出来单独一个类就行了
aaronysj
2020-05-21 08:54:23 +08:00
建议做法是把这种 @Bean 的注入,统一到一个单独的 Config 配置类中。
quarria
2020-05-21 08:57:17 +08:00
我也出现过这问题,原来 springboot2.0.3 的时候一点问题没有,升级到 2.2.6 就出现了这问题。第一种方法是在互相能循环调用的类上加懒加载的注解。第二种方法是实现 BeanFactoryPostProcessor 这个类中的 postProcessBeanFactory 方法。方法内写((AbstractAutowireCapableBeanFactory) beanFactory).setAllowRawInjectionDespiteWrapping(true); 这样就可以启动不报错了,但治标不治本,最终还是优化代码,尽量解耦,不出现循环调用的问题。
xiaofan2
2020-05-21 09:02:16 +08:00
setter 注入能产生循环依赖吗? 你的 PasswordEncoder 是自建的还是什么
aragakiyuii
2020-05-21 09:02:45 +08:00
再包一层

官方推荐用构造函数注入而非注解注入
yRebelHero
2020-05-21 09:09:53 +08:00
试试用 @Lazy ?不过一般这样就是设计出问题了。
linuxsteam
2020-05-21 09:10:16 +08:00
@SoulSleep 谢谢回答。
有提示三个类 我就是改了其中一个类为 new 对象的形式才解决的。

一会大家的方法我挨个试试,再次感谢
Foxkeh
2020-05-21 09:12:15 +08:00
szuwl
2020-05-21 09:13:14 +08:00
1. 懒加载
2. 重构(更改设计)
linuxsteam
2020-05-21 09:14:48 +08:00
@quarria 是的。你的那种做法,我在百度搜到了。但是无奈还得加代码(那个实现的类我还不了解,就放弃了)
linuxsteam
2020-05-21 09:19:52 +08:00
@xiaofan2 springsecurity 自带的。
Jrue0011
2020-05-21 09:43:17 +08:00
应该是不在 WebSecurityConfig 里注册 passwordEncoder,另外找个地方注册就行
cco
2020-05-21 10:00:09 +08:00
构造器注入就可以。
pomelotea2009
2020-05-21 12:53:05 +08:00
@Dachunlv 赞同,最简单的比如服务 A&B 循环依赖,你可以把服务 B 里对服务 A 的调用,挪到控制器里去做,在控制器里调用服务 A 之后,结果传参调用服务 B,原则上服务 A 和 B 也应该尽量隔离,除了一些小的工具服务
Chinsung
2020-05-21 17:43:46 +08:00
之前遇到过,首先逻辑最好理清楚,确实会有这样的问题,本地可以,服务器不行,如果实在不想大调整,或者 DependsOn 注解解决不了问题,可以把报错的那个类的 spring 配置类的包结构深度来改变顺序,我之前就是这么解决的
linuxsteam
2020-05-22 13:02:25 +08:00
@Chinsung 那就是说 浅的优先注入呗? 如果这样就行,这个适合懒人啊

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/673844

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX