美文网首页面试程序员Spring
阿里面试官居然不懂Spring是如何解决循环依赖的?

阿里面试官居然不懂Spring是如何解决循环依赖的?

作者: JavaEdge | 来源:发表于2022-02-01 16:36 被阅读0次

    BeanPostProcessor的after方法中会完成动态代理对象的创建。

    • 在创建代理对象之前,是否需要原始对象?
      需要原始对象!

    • 若刚开始先创建了原始对象,然后又创建了代理对象,则对外暴露引用时,应该用原始对象还是用代理对象呢?
      程序是写死的,没那么智能,说要判断用什么对象,所以我们需要保证,当bean需要被引用时,必须给出一个最终的结果:要么是原始对象,要么是代理对象,当生成代理对象时,原始对象会被覆盖掉。

    • 怎么确定对象什么时候对外暴露或者说对外引用呢?
      无法确定!所以有了三级缓存这个骚操作!有了三级缓存,每次在创建完对象后,不是直接把对象放到一级或二级缓存,而是先将一个lambda表达式放到三级缓存中,当需要被引用时,会优先从三级缓存中获取到lambda,然后根据lambda表达式处理结果判断到底是原始对象还是代理对象。
      getEarlyBeanReference在此方法中已唯一确定了对外暴露的对象到底是原始对象还是代理对象。

    当Bean产生循环依赖时,比如BeanA的构造方法依赖BeanB作为成员需要注入,BeanB也依赖BeanA,你觉得会出现什么问题呢?又有哪些解决方式呢?

    通过set方法去处理,背后的原理其实是缓存。
    主要解决方式:

    三级缓存

    singletonObjects

    一级缓存, Cache of singleton objects
    bean name --> bean instance。
    存放完整对象。

    earlySingletonObjects

    二级缓存, Cache of early singleton objects
    bean name --> bean instance 提前曝光的BEAN缓存。
    存放半成品对象。

    singletonFactories

    三级缓存, Cache of singleton factories
    bean name --> ObjectFactory。需要的对象被代理时,就必须使用三级缓存(否则二级就够了)。解决循环依赖中存在aop的问题
    存放 lambda 表达式和对象名称的映射。

    • spring中已经有了循环依赖的解决方案,为什么项目中还会出现循环依赖的问题?
      spring中现有的解决循环依赖问题的方案只是一种预防机制, 当符合此情况的时候可以解决,但是在实际的场景中会存在很多不匹配的情况,构造器的循环依赖是无法解决的!

    带着aop的实现来重新走一下刚刚执行的逻辑, 体会各个对象在程序运行过程中的流转过程,对象的三个缓存中的迁移过程,画个图,总结下,debug下,
    起始断点的入口在:finishBeanFactorylnitialization方法。


    image

    相关文章

      网友评论

        本文标题:阿里面试官居然不懂Spring是如何解决循环依赖的?

        本文链接:https://www.haomeiwen.com/subject/ihgkkrtx.html