【Spring系列】- Spring循环依赖

news2024/9/20 19:21:17

Spring循环依赖

😄生命不息,写作不止
🔥 继续踏上学习之路,学之分享笔记
👊 总有一天我也能像各位大佬一样
🏆 一个有梦有戏的人 @怒放吧德德
🌝分享学习心得,欢迎指正,大家一起学习成长!

在这里插入图片描述

文章目录

  • Spring循环依赖
    • 什么是循环依赖?
    • 如何解决循环依赖
      • 打破循环依赖
      • 提前AOP
        • 判断是否循环依赖
      • 一级缓存
      • 二级缓存
      • 三级缓存
    • 博文推荐

什么是循环依赖?

什么是循环依赖呢?简单来说就是beanA依赖于beanB,beanB依赖于beanA(也就是A类中使用了B类,B类使用了A类)。在bean创建的生命周期中,当创建了beanA的时候,会检索A对象内部中需要填充的对象,发现A中是需要用到B对象,会先去单例池中寻找,如果没有找到,就会去创建B的bean对象。在beanB的生命周期中,创建方式依然是相同的,因此也会去填充beanA,发现单例池中并没有A的bean对象,这样就造成了循环依赖。
在这里插入图片描述
我们可以看看两个相互依赖的bean的生命周期
在这里插入图片描述

如何解决循环依赖

两个bean对象在还没有创建成bean对象就由于相互的依赖而进入的循环,那么,要如何去解开他们的循环呢?在spring中会使用三级缓存。在springboot中有许多的解决方法,比如加配置,加注解等等操作。

打破循环依赖

想要打破循环依赖,就只需要一个缓存即可,也就是使用一个Map集合。简单的说就是将所需的对象存入里面,在检测单例池没有所需的bean对象的时候,就通过beanName去查找一级缓存,这里要特别注意的是,一级缓存此时存储的是普通对象,是通过构造方法实例化的对象。
在这里插入图片描述
使用map来存储对象,可见能够解除循环依赖,但是这里存储的是普通对象,而不是一个代理对象。那么要如何解决呢?

提前AOP

可以通过提前AOP来得到代理对象,再把代理对象存到map集合中。在实例化普通对象后,直接进行AOP,生成代理对象,再将代理对象存到map集合中,然后在后面也就不需要进行aop了。但是,并不是每次都将AOP提前的,是在发现了循环依赖才是需要去将AOP提前。

判断是否循环依赖

要判断是否循环依赖也不是很难,就只需要一个集合creatingSet<‘beanName’>。在实例化对象之前将这个bean的名字存到set集合中,表示这个bean对象正在创建中,等待依赖他的对象实例化后,会去判断set集合中是否有所依赖的beanName,如果有的话,就表示出现了循环依赖,这样就可以进行提前AOP。然而,在bean对象创建完毕并且添加到单例池之后,就要去吧set集合把这个beanName移除掉,不然就会造成每次都需要提前AOP。

一级缓存

一级缓存singletonObjects存放的是已经初始化好的bean,即已经完成初始化好的注入对象的代理

二级缓存

通过提前AOP获得的代理对象,是不能够直接加入到单例池中的。因为生成的代理对象是需要利用到普通对象的,而这时候的普通对象是不完整的(没有通过完整的生命周期),里面的属性可能是为空的。也会造成这个代理对象不是单例的。我们可以采用二级缓存earlySingletonObjects,将提前AOP生成的代理存放到earlySingletonObjects集合中。
在填充属性的时候,先到单例池寻找,没找到就去creatingSet看是否存在循环依赖,存在循环依赖之后就去earlySingletonObjects寻找是否有代理对象,没有再去提前AOP创建代理对象,并存入缓存中。在最后填充其他属性之后从二级缓存中去get代理对象,存入单例池中。

三级缓存

打破循环并不是只通过二级缓存,而是还需要一个三级缓存singletonFactory。addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));spring在创建bean的时候就会生成lambda表达式,存到三级缓存中。

protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) {
	Object exposedObject = bean;
	if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
		for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) {
			exposedObject = bp.getEarlyBeanReference(exposedObject, beanName);
		}
	}
	return exposedObject;
}

而执行lambda表达式就会去执行wrapIfNecessary这个方法

public Object getEarlyBeanReference(Object bean, String beanName) {
    Object cacheKey = this.getCacheKey(bean.getClass(), beanName);
    this.earlyProxyReferences.put(cacheKey, bean);
    return this.wrapIfNecessary(bean, beanName, cacheKey);
}

这个方法就能够去创建代理对象

Object proxy = this.createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;

三级缓存主要才是用来解决循环依赖。在实例化对象的时候就将lambda表达式存入三级缓存中,singletonFActories.put("beanName", addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)));这个表达式的bean实际上就是普通对象,最后会生成的是代理对象。当遇到循环依赖的时候,就会先去二级缓存找再去三级缓存找,并且一定会找到,找到的是lambda表达式,然后去执行lambda表达式去生成代理对象最后当道二级缓存中。

博文推荐

Spring 循环依赖及三级缓存_程序源程序的博客-CSDN博客_三级缓存


👍创作不易,如有错误请指正,感谢观看!记得点赞哦!👍

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

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

相关文章

JMeter入门教程(11) --关联

文章目录1.任务背景2.任务目标3.任务实操1.任务背景 当JMeter执行脚本时&#xff0c;伪装成浏览器&#xff0c;然后根据脚本&#xff0c;把当初真的浏览器所发过的内容&#xff0c;再对网站服务器重新发送一遍&#xff0c;JMeter企图骗过服务器&#xff0c;让服务器以为它就是…

010. 递增子序列

1.题目链接&#xff1a; 491. 递增子序列 2.解题思路&#xff1a; 2.1.题目要求&#xff1a; 给你一个整数数组 nums &#xff0c;找出并返回所有该数组中不同的递增子序列&#xff0c;递增子序列中 至少有两个元素 &#xff08;数组可能有重复的元素&#xff0c;相等的元素排…

IDOC的状态

这篇文章介绍IDOC Status的概念和它们的用途&#xff0c;明确IDOC status的类别&#xff0c;看一下完整的状态列表&#xff0c;包括INBOUND和OUTBOUND&#xff0c;还有入站和出站iDoc处理时iDoc状态的顺序。 另外还有监控SAP IDOC status的工具&#xff0c;比如AIF&#xff0c;…

推特营销引流入门指南

一、关注 当您关注另一个Twitter用户时&#xff0c;您进行订阅&#xff0c;即可立即阅读其内容分享。因此&#xff0c;请评估您关注的人&#xff0c;尤其是刚开始时。跟踪新用户的一种简单方法是找到他们的个人资料&#xff0c;然后单击“关注”按钮。 Twitter对于那些疯狂点…

机器学习笔记之受限玻尔兹曼机(三)推断任务

机器学习笔记之受限玻尔兹曼机——推断任务引言回顾&#xff1a;受限玻尔兹曼机的模型表示推断任务求解——后验概率(posterior)基于隐变量的后验概率求解基于观测变量的后验概率求解受限玻尔兹曼机与神经网络的联系引言 上一节介绍了受限玻尔兹曼机的模型表示(Representation…

C++图书管理系统(管理员-读者)

C图书管理系统&#xff08;管理员-读者&#xff09; 一、设计一款文字式交互的图书管理系统&#xff0c;要求具备注册登录、浏览图书、借还图书等基本功能&#xff1b; 二、要求以外部文件的形式存储书籍信息、馆藏记录、借阅记录、用户信息等。【可参考提供的书籍清单】 三…

如何批量查询搜狗收录?提升搜狗收录8个方法介绍

如何批量查询搜狗收录? 批量查询搜狗收录的具体流程如下&#xff1a; 1、打开站长工具 2、在域名输入框添加需要查询的域名 3、在功能选择区勾选需要查询的功能&#xff08;这里勾选搜狗是否收录&#xff0c;搜狗收录总数&#xff09; 4、提交查询&#xff0c;等待查询结果 …

Android样式和主题背景

简介&#xff1a; 本文将简单介绍Android样式与主题背景的相关内容 文章目录前言一、样式二、主题背景三、样式层次结构四、创建并应用样式五、自定义默认主题六、添加特定于版本的样式七、常见的主题风格总结前言 借助 Android 中的样式和主题背景&#xff0c;我们可以将应用…

十五管还原炉舟皿自动卸料单元

目  录 摘要 Ⅰ 1 绪论 1 1.1 十五管还原炉舟皿产生和发展 1 1.2十五管还原炉舟皿的今天与明天 2 2 总体方案设计 4 2&#xff0e;1自动卸料单元的作用 4 2&#xff0e;2十五管还原炉舟皿自动卸料单元结构的选择 4 2&#xff0e;3设计技术参数: 7 2&#xff0e;4 自动卸料单元…

Python实现基于物品的协同过滤推荐算法构建电影推荐系统

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 基于物品的协同过滤推荐&#xff08;Item-based CF&#xff09;的假设原理为&#xff1a;跟你喜欢的东西…

python的数据可视化

python画图1.使用pyecharts画图1.1 画地图1.1.1 画2D中国地图1.1.2 画2D世界地图1.1.3 画3D世界地图1.2 pyecharts的三种图片渲染工具1.2.1 snapshot_selenium1.2.2 snapshot_phantomjs1.2.3 snapshot_pyppeteer1.3 词云图1.3.1依据图片渲染出指定形状的词云图1.3.2渲染出指定大…

基于Android的学生信息管理App设计(Android studio开发)

目 录 一、 题目选择&#xff08;题目、选题意义&#xff09; 3 二、 设计目的 3 1、 初衷 3 2、 结合实际 3 3、 使用工具 3 三、 最终页面效果展示 4 1、 登陆界面 4 2、 主界面 5 3、 各个功能模块 6 四、 各部分设计 11 1、活动页面Activity布局文件 11 2、Activity的编程 …

基于JSP网上书城的设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

Figma UI UX设计教程

Figma UI UX设计教程 使用 Figma 获得 UI 设计、用户界面、用户体验设计、UX 设计和网页设计方面的工作 课程英文名&#xff1a;Figma UI UX Design Essentials 此视频教程共10.0小时&#xff0c;中英双语字幕&#xff0c;画质清晰无水印&#xff0c;源码附件全 下载地址 课…

毕业设计-基于机器视觉的行人车辆跟踪出入双向检测计数

目录 前言 课题背景和意义 实现技术思路 实现效果图样例 前言 &#x1f4c5;大四是整个大学期间最忙碌的时光,一边要忙着备考或实习为毕业后面临的就业升学做准备,一边要为毕业设计耗费大量精力。近几年各个学校要求的毕设项目越来越难,有不少课题是研究生级别难度的,对本科…

网格化微型空气质量站 浅谈工作原理

产品简介 网格化微型空气质量站是一种集数据采集、存储、传输和管理于一体的无人值守的环境监测系统&#xff0c;能全天候、连续、自动地监测环境&#xff0c;在提供PM10、PM2.5、 SO2、 NO2、CO、O3等参数数据的基础上&#xff0c;可扩展对VOCs、氯气、硫化氢、氨气等多种特征…

[附源码]Python计算机毕业设计Django勤工俭学管理小程序

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

Nginx的常用命令和配置文件

常用命令 1.查看 nginx版本号 在/usr/local/nginx/sbin 目录下执行 ./nginx -v 2.启动命令 在/usr/local/nginx/sbin 目录下执行 ./nginx 3.关闭命令 在/usr/local/nginx/sbin 目录下执行 ./nginx -s stop 4.重新加载命令 在/usr/local/nginx/sbin 目录下执行 ./nginx …

主流时序数据库分析及选型

目录一、当前主流的时序数据库二、主流时序数据库分析1、[Influxdb](https://docs.influxdata.com/influxdb)2、[Timescale](https://docs.timescale.com/)3、[Apache Druid](https://druid.apache.org/docs/latest/design/index.html)4、[Kdb](https://code.kx.com/home/)5、[…

牛客网基础知识强化巩固-周结04

链表强化训练 2022-11-28 打卡 知识点总结 磁盘字节和比特的问题 文件分配表FAT是管理磁盘空间的一种数据结构&#xff0c;用在以链接方式存储文件的系统中记录磁盘分配和跟踪空白磁盘块。整个磁盘仅设一张FAT表&#xff0c;其结构如下图所示。如果文件块号为2&#xff0c;查找…