Spring解决循环依赖的问题

网上找的很多描述是这样的:

A,B相互依赖, 创建A对象前先从各级缓存中获取, 没有就实例化A对象, 然后暴露自身工厂对象.

填充属性时发现需要B对象, 再从各级缓存中获取, 没有则实例化并且也暴露出去自身工厂对象,填充属性时发现依赖A对象就从各级缓存中获取.

singletonObjects和earlySingletonObjects中都没有, 在singletonFactories中发现了A的
工厂对象, 然后调用工厂对象的getObject方法得到了A对象, 将这个A对象放入earlySingletonObjects中, 再完成B对象的属性填充最后初始化B对象并将B对象添加到singletonObjects中, 删除其余俩缓存中的B相关数据

继续执行A对象的操作, A对象也能获取到B对象了, 也完成初始化并且添加到singletonObjects中

这样的描述感觉很模糊, 而且我有几个问题没有搞懂, 水平太差源码也没看明白所以想请大佬们帮帮忙:

  1. A工厂对象的getObject方法得到的A对象是和前面创建的A对象是同一个, 那从工厂对象得到的这个A对象是不是已经被加强成为了Bean对象?
  2. 然后注入到B对象当中的A属性中. 但是Spring中注入的不都是代理对象么, 代理对象怎么又能和创建时候的A对象是同一个呢, 是创建的这个A对象就是Bean对象吗?
  3. 如果不是的话什么时候注入的对象换成了Bean对象的, 并且B对象的操作完后返回的对象也不是Bean对象, A对象中的B属性又是什么时候换成了B对象关联的Bean对象, 容器中的单例对象都是Bean对象并且都是代理对象, 什么时候生成的代理对象并添加进容器的呢?
  4. 如果创建的是Bean对象, 那么原对象的后置处理器什么的和实现的aware接口假如要给原对象的一个属性赋值, 那么这里操作的不是原对象, 原对象的属性是什么时候以什么方式赋值的呢?
阅读 3.3k
4 个回答

我理解的你这些问题其实想问的就是autowired对象是原始对象还是代理对象的问题,你的理解是可能会先创建原始对象赋值给引用它的对象,之后可能bean又被替换成了代理对象,于是引用它的对象就引用错了。

其实不会发生这种问题,这个所谓的earlySingletonObject其实就是最终要是用的bean对象,如果这个bean是需要创建代理的,那earlySingletonObject也就是最终那个代理对象,不管是用构造器创建原始对象,还是给原始对象创建代理对象,这都算做是整个bean实例化的一部分,你可以理解成对外是一个原子操作,那当然就不会有“先创建一个原始对象赋值给其他对象,再创建一个代理作为最终bean”的情况。之所以叫它earlySingletonObject只是因为它还没填充成员变量没做初始化而已

之前一直觉得循环依赖很牛逼。不过我慢慢发现,这种设计本身有种"容忍坏气息的" 那种味道,这是对不规范的放纵,所以,如果有可能,不要想着它是怎么解决循环依赖的。而是如何防止循环依赖。

  1. 从工厂中获得的是这个对象的引用而已,此时的它只能算一个中间对象,因为并没有被填充任何信息。
  2. 从工厂中获取的对象就是代理对象,参考getEarlyBeanReference()。
  3. 因为是,所以不用回答了吧
  4. 后置处理器在解决了循环依赖问题后会继续加载。这类似于递归返回,终究有出口。出去了后,加载继续完成,并不受影响。

版本稍高的springboot已经不允许循环依赖了.
如果出现循环依赖, 证明代码质量有问题, 可以考虑使用MQ或者Spring自带的事件通知

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏