• Spring如何解决循环依赖


    spring如何解决循环依赖。相信大家都知道要通过三级缓存来解决,但具体的细节怎么样做的,可以一起来看一下。

    问什么会产生循环依赖,这就得从IOC说起了

    将对象交给容器控制,容器来创建对象,及其控制对象的生命周期。
    容器在实例化对象后,要注入属性,注入属性A的时候,A需要B,注入B的时候,B又需要A,这就导致了循环依赖。
    对于Bean的生命周期可以看这篇博客 Bean生命周期

    具体过程

    在这里插入图片描述

    • A创建过程中需要B,于是A将自己放到三级缓存里面,去实例化B
    • B实例化的时候发现需要A,于是B先查一级缓存,没有,再查二级缓存,还是没有,再查三级缓存,找到了A然后把三级缓存里面的这个A放到二级缓存里面,并删除三级缓存里面的A
    • B顺利初始化完毕,将自己放到一级缓存里面(此时B里面的A依然是创建中状态)然后回来接着创建A,此时B已经创建结束,直接从一级缓存里面拿到B,然后完成创建,并将A放到一级缓存中。

    那么分别用一级缓存两级缓存会出现什么问题呢?

    一级缓存

    实例化A -> 将半成品的A放入singletonObjects中->填充A的属性时发现取不到B->实例化B->从singletonObjects中取出A填充B的属性->将成品B放入singletonObjects->将B填充到A的属性中->将成品A放入singletonObjects。

    问题:这种基本流程是通的,但是如果在整个流程进行中,有另一个线程要来取A,那么有可能拿到的只是一个属性都为null的半成品A,这样就会有问题。

    二级缓存

    使用singletonObjects和earlySingletonObjects

    成品放在singletonObjects中,半成品放在earlySingletonObjects中

    流程可以这样走:实例化A ->将半成品的A放入earlySingletonObjects中 ->填充A的属性时发现取不到B->实例化B->将半成品的A放入earlySingletonObjects中->从earlySingletonObjects中取出A填充B的属性->将成品B放入singletonObjects,并从earlySingletonObjects中删除B->将B填充到A的属性中->将成品A放入singletonObjects并删除earlySingletonObjects。

    问题:这样的流程是线程安全的,不过如果A上加个切面(AOP),这种做法就没法满足需求了,因为earlySingletonObjects中存放的都是原始对象,而我们需要注入的其实是A的代理对象。

    因为切面时需要代理对象所以存在了三及缓存
    三级缓存是用来存储代理Bean,当调用getBean()方法时,发现目标Bean需要通过代理工厂来创建,此时会将创建好的实例保存到三级缓存,最终也会将赋值好的Bean同步到一级缓存中。

  • 相关阅读:
    深入理解AQS之ReentrantLock源码分析
    在 VSCode 中使用 GDB 进行 C/C++ 程序调试(图文版)
    易车:互联网造车定位称王还是镜花水月
    考察程序员功力的代码
    浅析GC-垃圾回收
    HTML网页大作业代码【免费代码已上传】
    政企版 WPS Pro 专业版注册安装教程
    让 GPT-4 来修复 Golang “数据竞争”问题(续) - 每天5分钟玩转 GPT 编程系列(7)
    HTML标签详解 HTML5+CSS3+移动web 前端开发入门笔记(四)
    一、初始化个人简历项目
  • 原文地址:https://blog.csdn.net/qq_44620773/article/details/127653253