spring的循环依赖和三级缓存

news2024/10/6 7:31:51
  1. 什么是循环依赖

    1. A引用了B,而这个时候B也引用了A,那么这种情况实际上就是出现了循环依赖的问题了,实际上也可以把循环依赖称之为循环引用,两个或者两个以上的bean互相持有对方,最终形成闭环
    2. 这里不是函数的循环调用,是对象的相互依赖关系,循环调用其实就是一个死循环,除非有终结条件,否则的话,他就是一个死循环
  2. spring的循环依赖

    1. spring的循环依赖有:
      1. 构造器的循环依赖
      2. field属性的循环依赖
    2. 构造器的循环依赖实际上是个无解的操作,只能抛出BeanCurrentlyInCreationException异常,也就是说,这个构造器导致的循环依赖,spring是没有办法来处理的,也只是给抛出了异常
  3. spring解决循环依赖

    1. spring的单例对象的初始化主要分为三个步骤
      1. createBeanInstance 实例化
      2. populateBean 填充属性
      3. initializeBean 初始化
    2. createBeanInstance实例化实际上就是调用对象的构造方法实例化对象
    3. populateBean实际上就是对bean的依赖属性进行一个赋值填充
    4. initializeBean则是调用spring xml中的int方法
    5. 但从bean的初始化的过程来看,循环依赖发生的位置就是在createBeanInstance实例化,以及populateBean填充属性中
    6. 发生的循环依赖是:构造器的循环依赖和field属性的循环依赖
  4. 三级缓存

    1. singletonFactories:单例对象工厂的cache,用于存放完全初始化好的bean,从该缓存中取出的bean可以直接使用

    2. earlySingletonObjects:提前曝光的单例对象的cache,存放原始的bean对象(尚未填充属性),用于解决循环依赖

    3. singletonObjects:单例对象的cache,存放bean工厂对象,用于解决循环依赖

      1. private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256); //一级缓存
        private final Map<String, Object> earlySingletonObjects = new HashMap<>(16); // 二级缓存
        private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16); // 三级缓存
        
  5. 对象创建过程

    1. AbstractBeanFactory 中的 doGetBean()方法

      1. protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly)
        
    2. DefaultSingletonBeanRegistry 中的 getSingleton()方法

      1. protected Object getSingleton(String beanName, boolean allowEarlyReference)
        
      2. 在这个方法中,先从一级缓存singletonObjects中去获取,如果获取到就直接return

      3. 如果获取不到,并且对象正在创建中,就再从二级缓存earlySingletonObjects中获取

      4. 如果还是获取不到且允许singletonFactories通过getObject()获取,就从三级缓存singletonFactory.getObject()获取

      5. 如果获取到了,则从singletonFactories中移除,并放入earlySingletonObjects中

      6. 这相当于把三级缓存中的数据剪贴到了二级缓存中

      7. protected Object getSingleton(String beanName, boolean allowEarlyReference) {
          Object singletonObject = this.singletonObjects.get(beanName);
          if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
           synchronized (this.singletonObjects) {
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
             ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
             if (singletonFactory != null) {
              singletonObject = singletonFactory.getObject();
              this.earlySingletonObjects.put(beanName, singletonObject);
              this.singletonFactories.remove(beanName);
             }
            }
           }
          }
          return singletonObject;
         }
        
    3. AbstractAutowireCapableBeanFactory 中的 doCreateBean() 方法

      1. protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        
         //添加到三级缓存
          if (earlySingletonExposure) {
           if (logger.isTraceEnabled()) {
            logger.trace("Eagerly caching bean '" + beanName +
              "' to allow for resolving potential circular references");
           }
           addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
          }
        
    4. AbstractAutowireCapableBeanFactory 中的 populateBean() 方法进行属性赋值

      1. protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw)
        
    5. AbstractAutowireCapableBeanFactory 中的 initializeBean() 初始化对象

      1. protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
        
  6. 解决

    1. spring解决循环依赖的诀窍就在于singletonFactories这个三级cache
    2. 这个cache的类型是ObjectFactory,这里就是解决循环依赖的关键,发生在createBeanInstance之后,也就是说单例对象此时已经被创建出来(调用了构造器)
    3. 这哦对象已经被生产出来了,虽然还不完美(还没有进行初始化的第二步和第三步),但是已经能被人认出来了(根据对象引用能定位到堆中的对象),所以spring此时将这个对象提前曝光出来让大家认识,让大家使用
  7. 二级缓存到底能不能解决

    1. 二级缓存也是能够实现的,如果自己想要实现,那么就得重写AbstractAutowireCapableBeanFactory的doCreateBean的方法

    2.      //添加到三级缓存
        if (earlySingletonExposure) {
         if (logger.isTraceEnabled()) {
          logger.trace("Eagerly caching bean '" + beanName +
            "' to allow for resolving potential circular references");
         }
         addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
         //从三级缓存中取出立刻放入二级缓存
         getSingleton(beanName, true);
        }
      
    3. 如果要使用二级缓存解决循环依赖,意味着Bean在构造完后就创建代理对象,这样违背了spring的设计原则

    4. spring结合AOP跟Bean的生命周期,是在Bean创建完全之后通过AnnotationAwareAspectAutoProxyCreator这个后置处理器来完成的,在这个后置处理的postPocessAfterInitialization方法中对初始化后的Bean完成AOP代理

    5. 如果出现了循环依赖,那没有办法,只能给Bean先创建代理,但是没有出现循环依赖的情况下,设计之初就是让Bean在生命周期的最后一步完成代理而不是在实例化后就立马完成代理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1905268.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从一个(模型设计的)想法到完成模型验证的步骤

从有一个大型语言模型&#xff08;LLM&#xff09;设计的想法到完成该想法的验证&#xff0c;可以遵循以下实践步骤&#xff1a; 需求分析&#xff1a; 明确模型的目的和应用场景。确定所需的语言类型、模型大小和性能要求。分析目标用户群体和使用环境。 文献调研&#xff1a…

前端html面试常见问题

前端html面试常见问题 1. !DOCTYPE (文档类型)的作用2. meta标签3. 对 HTML 语义化 的理解&#xff1f;语义元素有哪些&#xff1f;语义化的优点4. HTML中 title 、alt 属性的区别5. src、href 、url 之间的区别6. script标签中的 async、defer 的区别7. 行内元素、块级元素、空…

运维系列.Nginx:自定义错误页面

运维系列 Nginx&#xff1a;自定义错误页面 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/…

mac|Mysql WorkBench 或终端 导入 .sql文件

选择Open SQL Script导入文件 在第一行加入use 你的schema名字&#xff0c;相当于选择了这个schema 点击运行即可将sql文件导入database 看到下面成功了即可 这时候可以看看左侧的目标database中有没有成功导入table&#xff0c;如果没有看到的话&#xff0c;可以点一下右上角的…

【算法笔记自学】第 8 章 提高篇(2)——搜索专题

8.1深度优先搜索&#xff08;DFS&#xff09; #include <cstdio>const int MAXN 5; int n, m, maze[MAXN][MAXN]; bool visited[MAXN][MAXN] {false}; int counter 0;const int MAXD 4; int dx[MAXD] {0, 0, 1, -1}; int dy[MAXD] {1, -1, 0, 0};bool isValid(int …

执行力不足是因为选择模糊

选择模糊&#xff1a;执行力不足的根源 选择模糊是指在面对多个选项时&#xff0c;缺乏明确的目标和方向。这种模糊感会导致犹豫不决&#xff0c;进而影响我们的执行力。 选择模糊的表现&#xff1a; 目标不明确&#xff0c;不知道应该做什么。优先级混乱&#xff0c;不清楚…

【持续集成_03课_Jenkins生成Allure报告及Sonar静态扫描】

1、 一、构建之后的配置 1、安装allure插件 安装好之后&#xff0c;可以在这里搜到已经安装的 2、配置allure的allure-commandline 正常配置&#xff0c;是要么在工具里配置&#xff0c;要么在系统里配置 allure-commandline是在工具里进行配置 两种方式进行配置 1&#xff…

人工智能、机器学习、神经网络、深度学习和卷积神经网络的概念和关系

人工智能&#xff08;Artificial Intelligence&#xff0c;缩写为AI&#xff09;--又称为机器智能&#xff0c;是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。 人工智能是智能学科重要的组成部分&#xff0c;它企图了解智能的实质…

[护网训练]原创应急响应靶机整理集合

前言 目前已经出了很多应急响应靶机了&#xff0c;有意愿的时间&#xff0c;或者正在准备国护的师傅&#xff0c;可以尝试着做一做已知的应急响应靶机。 关于后期&#xff1a; 后期的应急响应会偏向拓扑化&#xff0c;不再是单单一台机器&#xff0c;也会慢慢完善整体制度。…

基于Java的企业客户信息反馈平台

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a; Java 数据库&#xff1a; MySQL 技术&#xff1a; Java MySQL B/S架构 SpringBoot框架 工具&#xff1a; Eclipse、MySQL环境配置工具、浏览…

【每日一练】python算数练习题(函数.随机.判断综合运用)

""" 幼儿园加减法练习题 答对点赞表情&#xff0c;答错炸弹表情 表情随机出现 如果全答对有大奖 """ import random df0 #定义答对函数 def dd():global dfdf10bq["&#x1f339;&#x1f339;&#x1f339;","&#x1f389;&…

试用笔记之-汇通窗口颜色显示软件(颜色值可供Delphi编程用)

首先下载汇通窗口颜色显示软件 http://www.htsoft.com.cn/download/wdspy.rar 通过获得句柄颜色&#xff0c;显示Delphi颜色值和HTML颜色值

【74LS163做24进制计数器】2021-11-19

缘由用74LS163做24进制计数器-其他-CSDN问答,仿真multisim两个74LS163芯片如何构成47进制计数器-吐槽问答-CSDN问答 参考74ls163中文资料汇总&#xff08;74ls163引脚图及功能_内部结构图及应用电路&#xff09; - 电子发烧友网

weblogic加入第三方数据库代理驱动jar包(Oracle为例)

做的是国企项目&#xff0c;项目本身业务并不复杂&#xff0c;最复杂的却是服务器部署问题&#xff0c;对方给提供的服务器分内网、外网交换网&#xff0c;应用在交换网&#xff0c;数据库在内网&#xff0c;应用不能直接访问内网数据库&#xff0c;只能通过安全隔离网闸访问内…

electron 初始使用

electron electron文档地址deno下载地址安装命令 yarn config set electron_mirror https://cdn.npm.taobao.org/dist/electron/ npm install下载文件 文件下载完成后&#xff0c;新建dist目录&#xff0c;解压到list目录下&#xff1b;path文件中写入electron.exe 运行命令 …

【三级等保】等保整体建设方案(Word原件)

建设要点目录&#xff1a; 1、系统定级与安全域 2、实施方案设计 3、安全防护体系建设规划 软件全文档&#xff0c;全方案获取方式&#xff1a;本文末个人名片直接获取。

Python28-7.5 降维算法之t-分布邻域嵌入t-SNE

t-分布邻域嵌入&#xff08;t-distributed Stochastic Neighbor Embedding&#xff0c;t-SNE&#xff09;是一种用于数据降维和可视化的机器学习算法&#xff0c;尤其适用于高维数据的降维。t-SNE通过将高维数据嵌入到低维空间&#xff08;通常是二维或三维&#xff09;中&…

尚品汇-(十四)

&#xff08;1&#xff09;提交git 商品后台管理到此已经完成&#xff0c;我们可以把项目提交到公共的环境&#xff0c;原来使用svn&#xff0c;现在使用git 首先在本地创建ssh key&#xff1b; 命令&#xff1a;ssh-keygen -t rsa -C "your_emailyouremail.com" I…

按键控制LED流水灯模式定时器时钟

目录 1.定时器 2. STC89C52定时器资源 3.定时器框图 4. 定时器工作模式 5.中断系统 1&#xff09;介绍 2&#xff09;流程图&#xff1a;​编辑 3&#xff09;STC89C52中断资源 4&#xff09;定时器和中断系统 5&#xff09;定时器的相关寄存器 6.按键控制LED流水灯模…

三丰云评测:免费虚拟主机和免费云服务器体验

近年来&#xff0c;随着互联网的快速发展&#xff0c;越来越多的人开始关注云计算服务。在众多云计算服务提供商中&#xff0c;三丰云备受关注&#xff0c;其免费虚拟主机和免费云服务器服务备受赞誉。今天我们就来进行一次三丰云的评测。首先让我们来看看三丰云的免费虚拟主机…