springIoc依赖注入循环依赖三级缓存

news2024/9/29 13:17:40

springIoc的理解,原理和实现

控制反转:

理论思想,原来的对象是由使用者来进行控制,有了spring之后,可以把整个对象交给spring来帮我们进行管理

依赖注入DI:

依赖注入,把对应的属性的值注入到具体的对象中,@autowired,populateBean完成属性的注入

容器

beanFactory,存储对象,使用map结构来存储,在spring中一般存在三级缓存,singletonObjects存放完整的bean对象,整个bean的生命周期,从创建初始化使用到销毁的过程都是容器来管理的

1,一般ioc容器的时候设计到容器的创建过程(beanFactory,DefaultListableBeanFactory)
2,加载解析bean对象,准备要创建的bean对象的定义对象 beanDefinition(xml或者注解的解析过程)
3,beanFactoryPostProcessor的处理,此处是扩展点,PlaceHolder
ConfigurSupport,ConfigurationClassProcessor.
4,BeanPostProcessor的注册功能,方便后续bean对象完成具体的扩展对象。
5,通过反射的方式将BeanDefinition对象实例化成具体的bean对象。
6,bean对象的初始化过程(填充属性,调用aware的子类方法,调用BeanPostProcessor前置处理方法,调用init-method方法,BeanPostProcessor的后置处理方法)

描述一下bean的生命周期

1,实例化bean,反射的方式生成对象
2,填充bean的属性:populateBean(),循环依赖的问题(三级缓存)
3,调用aware接口相关的方法:invokeAwareMethod(完成beanName可以获取容器bean的名称,BeanFactory获取当前bean factory这也可以调用容器的服务,BeanClassLoader对象的属性设置)
4,调用BeanPostProcessor中的前置方法:使用比较多的ApplicationContextPostProcessor设置ApplicationContext,Environment,ResourceLoader,EmbeddValueResolver等对象。
5,调用initmethod方法:invokeInitmethod(),判断是否实现了IntialzingBean接口,如果有,调用afterPropertiesSet方法。
6,调用BeanPostProceessor的后置处理方法:spring的aop就是在此实现的,AbstractAutoProxyCreator注册Destuction相关的回调接口。
7,通过getbean获取完整对象
8.销毁 判断是否实现了DisposableBean接口 destroyMethod方法
请添加图片描述

请添加图片描述

循环依赖

什么是循环依赖:

第一种互相依赖:A 依赖 B,B 又依赖 A,它们之间形成了循环依赖

在这里插入图片描述

第二种三者之间的依赖 A依赖B,B依赖C,C依赖A

在这里插入图片描述

第三种是自我依赖:A依赖A形成了循环依赖

在这里插入图片描述

三级缓存

  1. singletonObjects:缓存某个beanName对应的经过了完整生命周期的bean
  2. earlySingletonObjects:缓存提前拿原始对象进行了AOP之后得到的代理对象,原始对象还没有进行属性注入和后续的BeanPostProcessor等生命周期
  3. singletonFactories:缓存的是一个ObjectFactory,主要用来去生成原始对象进行了AOP之后得到的代理对象,在每个Bean的生成过程中,都会提前暴露一个工厂,这个工厂可能用到,也可能用不到,如果没有出现循环依赖依赖本bean,那么这个工厂无用,本bean按照自己的生命周期执行,执行完后直接把本bean放入singletonObjects中即可,如果出现了循环依赖依赖了本bean,则另外那个bean执行ObjectFactory提交得到一个AOP之后的代理对象(如果有AOP的话,如果无需AOP,则直接得到一个原始对象)。
public class DefaultSingletonBeanRegistry extends SimpleAliasRegistry implements SingletonBeanRegistry {
	/** Cache of singleton objects: bean name to bean instance. */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** Cache of singleton factories: bean name to ObjectFactory. */
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	/** Cache of early singleton objects: bean name to bean instance. */
	private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);
}

能否把一级缓存和二级缓存合并,只保留一个map结构来完成类似的功能?

理论上是可行的,一级缓存和二级缓存的value类型都是Object,都可以用来存放对象,只是对象的状态不同而已,所以当使用一个map的时候,只要给定具体的标识就可以解决这个问题,也就是说设置对象的时候,在value中不再直接存放对象,而是对象加标识位,比如0代表成品,1代表半成品,那么一个map就可以存储成品对象和办成品对象了,但是虽然可以这么干,没人会这么做,代码不优雅,而且每次在进行对象的存或者放的时候都要判断是否是成品对象,比较麻烦,直接用两个map结构解决即可

如果只有一级缓存和二级缓存,能否解决循环依赖的问题?

可以,但是有前提条件:没有aop的配置或者不需要创建代理对象的时候,两个map就可以解决循环依赖的问题

为什么三级缓存可以解决aop下的循环依赖问题?三级缓存到底有什么作用?

1,在同一个容器中,能否出现同名的不同对象?
不能,id是唯一标识

2,在同一个容器中,按照标准的生命周期,先创建了原始对象,后续又创建了代理对象,那时会怎么办?
当创建了代理对象之后,应该要使用代理对象的,但是原始对象已经存在,那么应该将原始对象给覆盖掉。getEarlyBeanReference()方法执行的逻辑是一样的

3,三级缓存到底有什么作用,为什么存在代理对象的时候就要使用三级缓存呢?
在标准的bean的生命周期中,要先创建出原始对象,创建出原始对象之后要使用populateBean方法来完成属性的赋值,此时赋值的对象是原始对象,因为代理对象还没有创建,代理对象的创建步骤是在BeanPostProcessor的后置处理方法中,也就是说已经完成赋值之后代理对象才创建出来,所以会报错(this means that said other beans do not use the final version of the bean),如何解决这个问题呢?

需要将代理对象的创建前置,也就是说在对象赋值的那一刻,要唯一性的确定出到底是原始对象还是代理对象,所以会优先把所有的bean都放到三级缓存中,在需要进行对象赋值的时候,从三级缓存中取出lambda表达式,lambda表达式的执行逻辑就是确定原始对象还是代理对象。如果是原始对象就赋值原始对象,如果是代理对象就赋值代理对象。

Spring中哪些情况下,不能解决循环依赖问题?

1,多例Bean通过setter注入的情况,不能解决循环依赖的问题。
当两个多例Bean相互依赖并且使用 Setter 方法注入时,Spring容器无法解决循环依赖。这是因为在多例模式下,每次请求获取一个新的Bean实例,Spring容器无法在创建Bean之前就确定依赖关系。
2,构造器注入的bean情况,不能解决循环依赖的问题。
循环依赖的产生:循环依赖通常在Bean的创建阶段发生,而构造器注入是在Bean创建之前发生的,因此无法通过构造器注入的方式解决已经发生的循环依赖。
3,设置了@DependsOn的Bean情况,不能解决循环依赖的问题。

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

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

相关文章

一文读懂「生成式AI,AIGC」

一、什么是AIGC&#xff1f; 二、技术层面发展 AIGC要素&#xff1a;算力 算法 数据 AIGC发展重点 AIGC产业链路 AIGC未来方向 三、产业层面发展 AIGC产业融资 AIGC场景应用 四、AIGC应用分析 AI 游戏 eg&#xff1a;网易伏羲 AI 广告营销 eg&#xff1a; AI 影…

vue使用i18n实现国际化

安装 npm install vue-i18nnext在src下创建一个名为i18n的文件夹,并按照下图创建需要的文件 i18n/locales/en.json {"common": {"BUTTON_OK": "OK","BUTTON_CANCEL": "Cancel","BUTTON_SUBMIT": "Submit…

虾皮广告数据分析:如何在虾皮(Shopee)平台上进行广告推广

在虾皮&#xff08;Shopee&#xff09;平台上进行广告推广是提高产品曝光率和销量的有效方式。通过采取一系列步骤&#xff0c;卖家可以充分利用Shopee的广告功能来推广产品。本文将介绍如何在Shopee上进行广告推广&#xff0c;并提供一些实用的技巧和建议。了解广告类型首先&a…

数据库——DAY4(练习-在表中查找数据-多表查询)

一、实验要求&#xff08;多表查询&#xff09; 素材&#xff1a; 1.创建student和score表 CREATE TABLE student ( id INT(10) NOT NULL UNIQUE PRIMARY KEY , name VARCHAR(20) NOT NULL , sex VARCHAR(4) , birth YEAR, department VARCHAR(20) , address VARCHAR(50) ); …

Tessy—嵌入式软件单元测试/集成测试工具

产品概述 Tessy源自戴姆勒—奔驰公司的软件技术实验室&#xff0c;由德国Hitex公司负责销售及技术的支持服务&#xff0c;是一款专门针对嵌入式软件进行单元/集成测试的工具。它可以对C/C代码进行单元、集成测试&#xff0c;可以自动化搭建测试环境、执行测试、评估测试结果并生…

yarn包管理器在添加、更新、删除模块时,在项目中是如何体现的

技术很久不用&#xff0c;就变得生疏起来。对npm深受其害&#xff0c;决定对yarn再整理一遍。 yarn包管理器 介绍安装yarn帮助信息最常用命令 介绍 yarn官网&#xff1a;https://yarn.bootcss.com&#xff0c;学任何技术的最新知识&#xff0c;都可以通过其对应的网站了解。无…

el-tree定义左边箭头,包括下级出现连线

效果图&#xff1a; 代码&#xff1a; <template><div class"agency-wrap"><el-treeclass"filter-tree":data"detailList":props"defaultProps"default-expand-allnode-click"onClickNode":filter-node-me…

基于springboot+vue的网上花卉商城系统(Java毕业设计)

大家好&#xff0c;我是DeBug&#xff0c;很高兴你能来阅读&#xff01;作为一名热爱编程的程序员&#xff0c;我希望通过这些教学笔记与大家分享我的编程经验和知识。在这里&#xff0c;我将会结合实际项目经验&#xff0c;分享编程技巧、最佳实践以及解决问题的方法。无论你是…

2、BERT:自然语言处理的变革者

请参考之前写的&#xff1a;2、什么是BERT&#xff1f;-CSDN博客文章浏览阅读826次&#xff0c;点赞19次&#xff0c;收藏22次。BERT&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;是Google在2018年提出的一种自然语言处理&#xff08;NLP&…

入门Docker1: 容器技术的基础

目录 服务器选型 虚拟机 基于主机(物理机或虚机)的多服务实例 基于容器的服务实例 Docker Docker三要素 Docker安装 Docker基本使用 基本操作 仓库镜像 容器 服务器选型 在选择服务器操作系统时&#xff0c; Windows 附带了许多您需要付费的功能。 Linux 是开放源代…

经营中东市场的跨境电商卖家看过来!亚马逊中东站热卖商品有哪些?

中东是跨境电商必须进入的一个大蓝海市场。目前亚马逊已经向中国卖家开放了17个站点&#xff0c;其中亚马逊中东站作为中东地区最大的电商平台&#xff0c;吸引了众多消费者的关注。作为亚马逊卖家&#xff0c;熟知跨境电商中东市场的热销选品对成功运营至关重要&#xff0c;今…

从零学Java 线程的状态

Java 线程的状态 文章目录 Java 线程的状态线程的基础状态1 常见方法1.1 休眠1.2 放弃1.3 加入1.4 优先级1.5 线程打断1.6 守护线程1.7 线程的状态 - 等待 2 线程安全问题2.1 线程同步: 同步代码块2.2 线程同步: 同步方法2.3 同步规则2.4 线程的状态 - 阻塞2.5 特殊现象: 死锁 …

用python提取PDF中各类文本内容的方法

从PDF文档中提取信息&#xff0c;是很多类似RAG这样的应用第一步要处理的事情&#xff0c;这里需要做好三件事&#xff1a; 提取出来的文本要保持信息完整性&#xff0c;也就是准确性提出的结果需要有附加信息&#xff0c;也就是要保存元数据提取过程要完成自动化&#xff0c;…

APM传感器校准

文章目录 前言一、校准加速度计二、校准罗盘三、校准陀螺仪四、校平地平线 前言 固件&#xff1a;rover 4.2.3 地面站&#xff1a;独家汉化版QGC 一、校准加速度计 点击左上角软件图标-》载具设置-》传感器-》加速度计 飞控方向默认为None即可&#xff0c;点击确定 点击确…

做品牌,怎么挖掘用户深层需求?

品牌想要长久发展&#xff0c;就需要去挖掘用户深层需求&#xff0c;什么是用户深层需求&#xff0c;比如做美业的认为用户想要变美是深层次的需求&#xff0c;但其实由美貌带来的附加利益比如说更上镜、竞争优势更大等才属于深层需求&#xff0c;今天媒介盒子就来和大家聊聊&a…

MySQL——SQL语句进阶

select * from 表 where 条件 group by 条件 order by 排序 limit 分组 Group by select * from 表 group by 条件 结果为每个分组的第一条记录&#xff0c;该条记录作为该组的标志 select * from subject GROUP BY gradeidselect count(1),gradeid from subject GROUP B…

图书管理系统:从数据库设计到前端展示的实战经验分享

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

Pytorch函数——torch.gather详解

在学习强化学习时&#xff0c;顺便复习复习pytorch的基本内容&#xff0c;遇到了 torch.gather()函数&#xff0c;参考图解PyTorch中的torch.gather函数 - 知乎 (zhihu.com)进行解释。 pytorch官网对函数给出的解释&#xff1a; 即input是一个矩阵&#xff0c;根据dim的值&…

网络文件共享服务、FTP和yum仓库

目录 一、存储类型 1、存储类型一共分为三种&#xff1a; 2、三种存储架构的应用场景 二、FTP文本传输协议 1、FTP工作原理介绍 2、FTP数据连接模式 3、svftpd的安装和配置 4、vsftpd的配置作用 5、黑名单和白名单的使用&#xff08;简要介绍&#xff09; 三、YUM 1…

1.15 作业

使用计数型信号量设计 2&#xff0c;相关函数的API 一、队列&#xff1a; 1&#xff0c;创建队列函数 osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr); msg_count : 队列中消息的最大数量&#xff0c;即…