spring三级缓存解决循环依赖

2023-11-08

一、循环依赖:

简单说就是 A类中有B属性,B类中有A属性。创建A对象时发现有B属性,就开始创建B对象,此时时又发现B对象中有A属性,又要创建A对象,产生循环依赖现象。示例图:

二、Spring解决循环依赖

使用缓存解决循环依赖的流程图

spring的三级缓存

一级缓存(singletonObjects):单例池,已经完成实例化、初始化的对象。

二级缓存(earlySingletonObjects):早期单例对象,已经实例化、未初始化的对象。用于决绝循环依赖问题。

三级缓存(singletonFactoryies):单例工厂,存放对象的lambda表达式。用于解决存在代理的循环依赖问题。

创建过程

创建过程中标志性的方法:   

创建过程流程图:

 

1、创建A

步骤一:查找A

查询一级缓存 -----> 查询二级缓存----> 查询三级缓存

三个级别的缓存中都没有A,创建A

步骤二:创建A

调用lambda的getObjtct()方法,执行 createBean() 操作。

createBean内部会执行方法:createBean ---> doCreateBean ---> createBeanInstance ---> instantiateBean ---> populateBean

A示例化后,会将A示例、beanName、RootBeanDefiniton封装成lambda表达式,放到三级缓存中,待出现循环依赖时使用。

步骤三:A填充属性

执行 AbstractAutowireCapableBeanFactory 类的 createBean 中 populateBean,给A填充属性。

填充B属性:获取B,执行获取B的操作(执行下面步骤:2、创建B)

步骤四:初始化A

确定最终的A,如果没有AOP代理操作,直接返回原始对象,如果存在AOP代理,返回的就是代理对象A。

将初始化之后的A放到一级缓存中。

2、创建B

步骤一:查找B

查询一级缓存 -----> 查询二级缓存----> 查询三级缓存,没有发现B,执行实例化B的操作。

步骤二:创建B

执行方法:createBean ---> doCreateBean ---> createBeanInstance ---> instantiateBean

步骤三:B填充属性

执行 populateBean()方法进行属性填充。填充B实例中A的属性,开始获取A:

      查找A:查询一级缓存 -----> 查询二级缓存----> 查询三级缓存,发现三级缓存汇总有A:执行lambda表达式获得最终的A实例;将A实例放到二级缓存中,并三级缓存中删除。     

     

提前暴露A:A正在创建中,此时对象B需要A对象,就会提前将A对象暴露出来,放到二级缓存中。此时的A是半成品,但却是最终的类型(原始类型/代理类型)

     得到A实例之后,将值复制给B实例的A属性。此时B对象填充完毕。

步骤四:初始化B

确定最终的B,如果没有AOP代理操作,直接返回原始对象,如果存在AOP代理,返回的就是代理对象B。将初始化之后的B放到一级缓存中。

此时回到给A填充属性步骤:将B实例赋值给A实例的B属性,A实例化完成。之后对A初始化,得到最终的A对象,并将A对象放到一级缓存(单例池)中,A创建完成。

三、问题

1、为什么三级缓存的作用主要是解决aop循环依赖问题?

        代理对象实现:首先通过实例化生成原始对象,再通过初始化生成代理对象。

        当出现循环依赖时,会出现对象还未初始化完成,就需要被暴露使用。此时必须确定出到底是原始对象还是代理对象。所以通过lambda表达式的方式,相当于一中回调机制来确定出最终是代理对象还是原始对象。

填充对象属性、实例化对象:

B填充属性时需要提前暴露出来A,即执行三级缓存中的lambda表达式:

A实例化完成,B实例化、初始化完成时,循环依赖效果图:

        此时A是原始对象,A中的B属性是最终对象,B对象中的A属性是最终的代理对象。A执行完初始化之后,也会变成代理对象被放入一级缓存。

         假如没有三级缓存,此时A对象是原始对象,B对象中的A对象也是原始对象。A经过初始化之后生成代理对象被放入一级缓存中。此时最终的A对象是代理对象,B使用的是A的原始对象,将会出现对象不一致的问题。

        

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

spring三级缓存解决循环依赖 的相关文章

随机推荐

  • linux与freertos程序兼容,从freeRTOS运行应用程序

    FreeRTOS 以及大多数RTOS 不像通用操作系统 GPOS 那样工作 它们通常不是为了动态加载和执行任意用户提供的应用程序而设计的 在大多数情况下 您使用RTOS是因为您需要硬实时响应 并且执行第三方代码可能会对此造成影响 大多数RT
  • vivado AXI_interconnector ID信号的一些总结

    很久没有写东西了 最近尽力了很多生活上的事情 最终也算圆满结局 言归正传 主要是以AXI4为背景介绍4组ID信号 以及其计算方式 对照vivado PG059以及PG247 见解都是基于个人所学 会有偏差还望谅解 AXI4中去掉了WID 所
  • 基于iframe的HTTP长连接实现

    关于什么是http长连接我不废吐沫了 有专业的解释 http www ibm com developerworks cn web wa lo comet 你可以去看看我们介绍一下在struts下的实现首先写一个test jsp 写一些片段
  • 【100天精通python】Day30:使用python操作数据库_数据库基础入门

    专栏导读 专栏订阅地址 https blog csdn net qq 35831906 category 12375510 html 1 数据库基础知识介绍 1 1 什么是数据库 数据库是一个结构化存储和组织数据的集合 它可以被有效地访问
  • android 网络自动同步时间慢问题

    问题描述 今天测试提了一个网络同步时间慢的bug 网络同步时间原理参考 https blog csdn net yin1031468524 article details 65447849 核心代码在NetworkTimeUpdateSer
  • 【遗传算法】【处理图像类问题】

    文章目录 一 前言 二 问题描述 三 算法介绍 四 其他知识点 Reference 一 前言 近期感兴趣的算法 以前没这么好奇过一个算法 时间没想象的焦虑 认真做一些事情 算法入门篇 二 问题描述 从前 一群扇贝在海岸边悠哉游哉地生活着 它
  • ThinkPHP3.2自带的七牛云配置使用

    利用七牛云私有空间存储文件 第一步 注册七牛云 创建空间 将空间设为私有 需要记下的东西 accessKey secrectKey domain bucket 第二步配置ThinkPHP 在config php添加 UPLOAD SITEI
  • STM32 FreeRTOS 内存问题

    1 STM32L151C8T6 内存 64Kb 的Flash 代码就是烧录在这里面的 16Kb 的RAM 程序跑起来之后的内存 相当于我们高考时发的草稿纸 直接影响程序的运行速度 可以用STM32 CubeMx 软件直接下载数据手册data
  • Calendar 中getActualMaximumd 功能

    String str new SimpleDateFormat yyyy MM dd HH mm ss SSS format new Date Calendar calendar Calendar getInstance Locale CH
  • 使用pytorch训练DCGAN----贰(代码解析)

    使用pytorch训练DCGAN 代码解析 上一篇 使用pytorch训练DCGAN 壹 这里我使用的代码时pytorch官方提供的源码 然后根据DCGAN原论文分板块分析 板块一 导包 from future import print f
  • javaWeb图书管理系统

    javaWeb图书管理系统 1 项目简单介绍 a 项目用到的技术 IDE Intellij IDEA 语言 java html ajax js 数据库 Mysql 数据库可视化 navicat web服务器 Tomcat 框架 mybati
  • C++使用当multiset插入相同的数时 新插入的数在已有数的左边还是右边呢

    答案 在multiset中 元素按照特定的顺序进行排序并存储 当向multiset插入相同的数时 新插入的数将被放置在已有数的右边 multiset允许存储重复的元素 并且保持了元素的顺序 因此 如果已经存在相同的数 新插入的数将被放置在它
  • c++在线编辑器

    c 在线编辑器 Compiler Explorer Coliru Ideone 乱糟糟的不推荐 C Shell CodingGround 可用来美化代码 慢的很 Judge0 IDE Compiler Explorer https godb
  • P1088 [NOIP2004 普及组] 火星人(全排列)

    题目链接 火星人 思路分析 分析题目题意得到 这个题目关于全排列的问题 题目输入N M分别代表对1 N进行全排列 火星人给出的大数就是1 N全排列的一种情况 对全排列的所有情况进行编号 例如下图 例如上图N 3 假设M 2 给出一种全排列序
  • ffmpeg推流收流 1920*1080视频 花屏

    自己用ffmpeg推流 然后再收流 小分辨率没有问题 当分辨率为1920 1080时 出现花屏现象 尤其是码率高时 现象更加明显 尝试各种办法 最后用下面的办法解决 在ffmpeg源码udp c中 define UDP MAX PKT SI
  • Ubuntu22.04配置静态IP-网关-DNS

    要在Ubuntu系统中配置网络 可以通过以下步骤进行操作 1 打开终端 可以使用 Ctrl Alt T 快捷键打开终端 或者从应用程序菜单中找到 终端 2 检查网络接口 输入以下命令检查当前系统中的网络接口列表 ifconfig a 接口列
  • 贝叶斯网络python实战(以泰坦尼克号数据集为例,pgmpy库)

    文章目录 贝叶斯网络简介 贝叶斯推断思路 贝叶斯网络 贝叶斯网络的实现 应用步骤 泰坦尼克数据集背景介绍 模型结构搭建 模型参数构建 贝叶斯估计器 推理 自动设计网络结构 gt 使用结构学习方法 模型保存 先验 练手数据集 Binary C
  • 三大排序算法

    目录 大O和推导过程 冒泡排序 冒泡排序的思路 冒泡排序的实现 冒泡排序的效率 O N 选择排序 选择排序的思路 选择排序实现 选择排序的效率 O N 插入排序 插入排序的思路 插入排序的实现 插入排序的效率 O N 大O和推导过程 公司规
  • 2023美赛C题:预测Wordle结果-思路详解及参考代码

    一 题目解析 总体来看与去年的C题比较相似 唯一一道有数据 不需要自己额外找 的题目 选题人估计也最多 本质是数据分析题目 需要建立预测模型 分类模型 特征挖掘等 相对来说出思路比较简单 想出彩比较难 所以在分析建模时一定要多维度思考 不然
  • spring三级缓存解决循环依赖

    一 循环依赖 简单说就是 A类中有B属性 B类中有A属性 创建A对象时发现有B属性 就开始创建B对象 此时时又发现B对象中有A属性 又要创建A对象 产生循环依赖现象 示例图 二 Spring解决循环依赖 使用缓存解决循环依赖的流程图 spr