Spring 出现循环依赖 (Is there an unresolvable circular reference?) 哪种解决方式最好? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
linuxsteam
V2EX    Java

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

  •  
  •   linuxsteam 2020-05-21 08:19:33 +08:00 6298 次点击
    这是一个创建于 2037 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    • 目前小弟只成功使用了一个不能称之为办法的解决办法,就是不交给 Spring,直接 new 一个对象.此贴想抛砖引玉 学习大家的解决办法。

    图 1 图 2 图 3

    请问

    • 问题 1SpringIOC 是不是通过 @ComponentScan 去把扫描到的相关带有注解的类注入到 Bean 中吗?
    • 问题 2继续上个问题(见图 2 ),注入顺序我说的是否正确?
      1. 先将 WebSscurityConfig 注入到 Bean 中
      2. 然后再将需要的 CustomAuth....注入到 Bean
      3. 最后将 passwordEncoder 注入到 Bean
    • 扣题如果我想解决上述代码导致的循环依赖,我并不想使用 new 一个 PasswordEncoder 的方式(见图 3 )解决循环依赖,有没有更优雅的办法?
      1. 个人尝试了 @Postconstruct (见图 2 ) 29 行 /46 行插入这个注释 启动项目还是报错
      2. 还没想出来...
    20 条回复    2020-05-22 13:02:25 +08:00
    SoulSleep
        1
    SoulSleep  
       2020-05-21 08:31:46 +08:00
    现在版本的 Spring 不会在日志里打印出你循环依赖的三个类吗?

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

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


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

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

    一会大家的方法我挨个试试,再次感谢
    Foxkeh
        12
    Foxkeh  
       2020-05-21 09:12:15 +08:00
    szuwl
        13
    szuwl  
       2020-05-21 09:13:14 +08:00
    1. 懒加载
    2. 重构(更改设计)
    linuxsteam
        14
    linuxsteam  
    OP
       2020-05-21 09:14:48 +08:00
    @quarria 是的。你的那种做法,我在百度搜到了。但是无奈还得加代码(那个实现的类我还不了解,就放弃了)
    linuxsteam
        15
    linuxsteam  
    OP
       2020-05-21 09:19:52 +08:00
    @xiaofan2 springsecurity 自带的。
    Jrue0011
        16
    Jrue0011  
       2020-05-21 09:43:17 +08:00
    应该是不在 WebSecurityConfig 里注册 passwordEncoder,另外找个地方注册就行
    cco
        17
    cco  
       2020-05-21 10:00:09 +08:00
    构造器注入就可以。
    pomelotea2009
        18
    pomelotea2009  
       2020-05-21 12:53:05 +08:00 via Android
    @Dachunlv 赞同,最简单的比如服务 A&B 循环依赖,你可以把服务 B 里对服务 A 的调用,挪到控制器里去做,在控制器里调用服务 A 之后,结果传参调用服务 B,原则上服务 A 和 B 也应该尽量隔离,除了一些小的工具服务
    Chinsung
        19
    Chinsung  
       2020-05-21 17:43:46 +08:00
    之前遇到过,首先逻辑最好理清楚,确实会有这样的问题,本地可以,服务器不行,如果实在不想大调整,或者 DependsOn 注解解决不了问题,可以把报错的那个类的 spring 配置类的包结构深度来改变顺序,我之前就是这么解决的
    linuxsteam
        20
    linuxsteam  
    OP
       2020-05-22 13:02:25 +08:00
    @Chinsung 那就是说 浅的优先注入呗? 如果这样就行,这个适合懒人啊
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3213 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 11:34 PVG 19:34 LAX 03:34 JFK 06:34
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86