spring神奇的循环依赖

故事

在开发中,本地代码稳定运行,测试环境也没问题,而生产环境发生了循环依赖,发布失败了。糟糕,生产发布失败可是大事情。开始着手解决。

现象

看看错误先
Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name ‘customizeThreadServiceImpl’: Bean with name ‘customizeThreadServiceImpl’ has been injected into other beans [testStepServiceImpl,agileTestDetailServiceHelper,agileDemandServiceHelper,agileTaskOperationLogic,agileDemandRelationServiceHelper,agileTestPlanServiceHelper,agileStoryOperationLogic,issueViewServiceImpl] 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.

分析

看上面的报错,很明显原因是customizeThreadServiceImpl注入其他类的时候,发生了循环依赖,注入失败了

解决办法

  1. 使用@Lazy的注解,注解到发生循环依赖的类引入上(最简单)
	@Lazy
    @Resource
    private CustomizeThreadService threadService;
  1. 去除循环依赖,改造代码(困难但必要)
    因为发生循环依赖的根源还是代码设计不合理,产生的循环依赖,要从根源上解决,就是从设计程序的基础上就应该规划好,及早预防
  2. InitializingBean时,从context中获取(不推荐)
  3. @PostConstruct去设置bean依赖(不推荐)

到这里还是没搞明白为什么本地不会循环依赖,测试环境也不会,为什么生产就会呢

真正的原因

在不同的操作系统或者环境下,bean的加载顺序是不固定的。bean加载顺序变化之后,就可能导致循环依赖的产生。因为顺序变化之后,循环依赖的主体发生变化。

bean加载时,会先将所有的BeanDefinition扫描出来,扫描出来的顺序基本上决定了bean的加载顺序。

扫描BeanDefinition的方法是ClassPathScanningCandidateComponentProvider#scanCandidateComponents(),这个方法在不同的环境下扫描出类的顺序是不固定的,它底层走的是java.lang.ClassLoader#getResources,这个方法没有承诺获取到资源文件的顺序

总结

遇到这种循环依赖,不要心存侥幸,还是要着手解决为妙

遇事总结,分享工作趣事,祝我们都工作顺利。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值