Spring Bean 的生命周期

news2025/1/10 13:50:17

文章目录

    • 一、前言
    • 二 、Bean 的生命周期
      • 2.1 Bean 的定义信息
      • 2.2 Bean 的创建
      • 2.3 Bean 的使用
      • 2.4 Bean 的销毁
      • 2.5 循环依赖
        • 2.5.1 什么是循环依赖
        • 2.5.2 Spring 解决循环依赖
          • 2.5.2.1 三级缓存
          • 2.5.2.2 提前暴露
        • 2.5.3 注意
          • 2.5.3.1 三级缓存结构中 map 分别存储什么类型对象
          • 2.5.3.2 三级缓存结构进行对象查找时,顺序是什么?
          • 2.5.3.3 如果只有一个 map 结构可以解决循环依赖问题吗?
          • 2.5.3.4 如果只有两个 map 结构 可以解决循环依赖吗?
          • 2.5.3.5 为什么使用三级缓存可以解决带 AOP 的循环依赖问题


一、前言

本文将图文并茂的为你讲述spring 中 bean 的生老病死!!!


二 、Bean 的生命周期

生命周期: 从对象的创建到使用到销毁的过程

在这里插入图片描述

2.1 Bean 的定义信息

BeanFactory: Bean 工厂,是 Spring 的一个根接口

PostProcessor:后置处理器

  • BeanFactoryPostProcessor: 处理 Bean 的定义信息 BeanDifinition

  • BeanPostProcessor:修改 Bean 的信息

请添加图片描述

请添加图片描述

2.2 Bean 的创建

Aware 接口:

当容器中创建的 Bean 对象需要进行具体操作时,需要容器的其他对象,可以实现 Aware 接口,来进行操作,用于二次开发。

在这里插入图片描述

2.3 Bean 的使用

在 Bean 创建时,属性赋值完成后,理论上 Bean 对象已经可以拿来使用了,但是Spring 考虑扩展性,会对 Bean 再做一些处理,完成初始化后即可调用

2.4 Bean 的销毁

Bean的销毁是在 Spring 容器关闭时进行销毁,及context.close()方法。

2.5 循环依赖

Spring 中的 Bean 默认情况下是单例的

2.5.1 什么是循环依赖

A 对象内包含了属性 b,B 对象内包含了属性 a。对 A 对象进行实例化后,对 b 属性赋值,这时候会引用 B 对象,判断 容器中是否有 B 对象,有则赋值,无则创建,B同理,这样程序就会报循环依赖的错误。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z7FZO4LG-1675153914716)(img/循环依赖.svg)]

2.5.2 Spring 解决循环依赖

解决方案:三级缓存、提前暴漏对象

当持有了某一个对象的引用之后,能否在后续步骤中给对象进行赋值操作?

可以,这样就可以解决循环依赖,其解决循环依赖的本质是 Bean 的实例化和初始化可以分开执行

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gOPcWWyL-1675153914716)(img/Spring 循环依赖.svg)]

2.5.2.1 三级缓存

DefaultSingletonBeanRegistry 源码

	/**
	* 一级缓存
	* Cache of singleton objects: bean name to bean instance. */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/**
	* 三级缓存
	* 用于保存 BeanName 和 创建 Bean 的工厂之间的联系
	* Cache of singleton factories: bean name to ObjectFactory. */
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

	/**
    * 二级缓存
    * 保存 BeanName 和 创建 Bean 实例之间的联系,与 singletonFactories 的不同在于,当单例 Bean 被放到这里后,就可以通过 getBean 方法获取到,可以方便进行循环依赖的检测
    * Cache of early singleton objects: bean name to bean instance. */
	private final Map<String, Object> earlySingletonObjects = new ConcurrentHashMap<>(16);

一级缓存二级缓存三级缓存
实例化对象类型ConcurrentHashMapConcurrentHashMapHashMap
容量2561616
泛型ObjectObjectObjectFactory

ObjectFactory:不是对象工厂,是函数式接口

@FunctionalInterface
public interface ObjectFactory<T> {

/**
    * Return an instance (possibly shared or independent)
    * of the object managed by this factory.
    * @return the resulting instance
    * @throws BeansException in case of creation errors
    */
   T getObject() throws BeansException;

}

jdk1.8后可以将 lambda 表达式作为参数放到方法的参数中,在方法执行的时候,并不会实际调用当前 lambda 表达式,只有在调用 getObject 方法的时候再回去调用 lambda 表达式

2.5.2.2 提前暴露

提前暴露指的是在 Bean 创建完成前 将对象暴露出去,Spring 在解决循环依赖问题时,在实例化后就将未创建完成的 Bean 的 ObjectFactory 放到 三级缓存,这样就把 Bean 提前暴露出去。

2.5.3 注意

2.5.3.1 三级缓存结构中 map 分别存储什么类型对象

一级缓存:成品对象

二级缓存:半成品对象

三级缓存:lambda 表达式

2.5.3.2 三级缓存结构进行对象查找时,顺序是什么?

一级缓存 ==> 二级缓存 ==> 三级缓存

2.5.3.3 如果只有一个 map 结构可以解决循环依赖问题吗?

理论上可行,实际没人这么干

使用两个 map 的意义在于 将成品对象和半成品对象进行区分,半成品对象不能暴露给外部使用,可以设置 标识位进行区分,但是操作比较麻烦,所以直接使用两个 map

2.5.3.4 如果只有两个 map 结构 可以解决循环依赖吗?

可以解决,但是前提是 没有使用代理对象的时候,当不使用 AOP 的时候, 两个 map 就可以解决循环依赖问题

2.5.3.5 为什么使用三级缓存可以解决带 AOP 的循环依赖问题
  • 一个容器中不能包含同名对象

  • 对象创建过程中,扩展阶段 原始对象有可能需要生成代理对象

  • 当代理对象出现时,要使用代理对象替换掉原始对象

  • 代理对象的创建是在初始化过程的扩展阶段,需要在前置处理过程的时候判断是否需要生成代理对象

  • 为什么使用 lambda 表达式(函数式接口)

    因为对象什么时候被暴露或被引用无法提前预知,所以只有在被调用的时候才可进行原始对象还是代理对象的判断,使用 lambda 表达式延迟执行的优点,类似于一种回调机制,不暴露的时候不执行,当需要被调用的时候才真正执行 lambda 表达式,来判断返回的是代理对象还是原始对象

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

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

相关文章

JVM-内存与垃圾回收-1.JVM与Java体系结构

1.JVM与Java体系结构 1. JVM&#xff1a;跨语言的平台 Java是目前应用最为广泛的软件开发平台之一。随着Java以及Java社区的不断壮大Java 也早已不再是简简单单的一门计算机语言了&#xff0c;它更是一个平台、一种文化、一个社区。 ● 作为一个平台&#xff0c;Java虚拟机扮…

机器人中的数值优化之BFGS(nonconvex and smooth)

本文ppt来自深蓝学院《机器人中的数值优化》 目录 1 wolfe conditions 2 cautious update 3 BFGS for nonconvex functions 1 wolfe conditions 当我们需要搜索方向是下降方向时&#xff0c;一定要让近似hessian的矩阵正定&#xff0c;这就需要满足wolfe条件 首先需要满…

34. 实战:基于某api实现歌曲检索与下载(附完整源代码)

目录 前言 &#xff08;相关链接在评论区&#xff09; 目的 &#xff08;相关链接在评论区&#xff09; 思路 &#xff08;相关链接在评论区&#xff09; 代码实现 1. 访问某音乐平台&#xff08;链接放在评论区了&#xff09;&#xff0c;抓包搜索接…

BUUCTF reverse题解汇总

本文是BUUCTF平台reverse题解的汇总 Page1 easyrereverse1reverse2内涵的软件新年快乐xorhelloworldreverse3不一样的flagSimpleRevJava逆向解密[GXYCTF2019]luck_guy[BJDCTF2020]JustRE刮开有奖简单注册器pyre[ACTF新生赛2020]easyrefinditrsa[ACTF新生赛2020]rome[FlareOn4]…

穿越寒冬春暖花开,当下便是在社科院杜兰金融管理硕士项目读研的好时光

时间无声的从指尖划过&#xff0c;严寒的冬天已经过去&#xff0c;春天即将到来。23考研期间&#xff0c;恰逢特殊时期&#xff0c;好多同学错失了考试的机会&#xff0c;忧心2023是否还可以读研。不要担心&#xff0c;免联考的社科院与杜兰大学金融管理硕士项目来了&#xff0…

【html】如何处理显示ttf字体图标

当看到某些文件的后缀名是ttf&#xff0c;表示是字体文件&#xff0c;除了显示字体&#xff0c;还能显示图标&#xff0c;如果需要显示的图标太多&#xff0c;就把它们放在一个文件中&#xff0c;方便统一管理图标&#xff0c;在此讲一下怎么显示字体图标。 打开文件 电脑上用…

超低损耗电路新研究:光芯片电路+量子计算

&#xff08;图片来源&#xff1a;网络&#xff09;在光通信以及使用光而不是电荷来存储和传输信息的量子计算机的设计中&#xff0c;要做到以最小的损耗传输&#xff0c;并能操纵最小单位光&#xff0c;光子起着至关重要的作用。现在&#xff0c;美国国家标准与技术研究院的研…

DynaSLAM-4 DynaSLAM中Mask R-CNN部分源码解析(Ⅲ)

目录 1.RPN 1.1 RPN层的作用与实现解读 1.2 候选框过滤ProposalLayer层 2. DetectionTargetType层 2.1 DetectionTargetType层作用 2.2 正负样本选择与标签定义 1.RPN 1.1 RPN层的作用与实现解读 上篇博客中我们解释了如何通过generate_pyramid_anchors在每一个特征层上…

Nacos学习:一、Nacos注册中心

Nacos 1. Nacos注册中心 ​ 国内公司一般都推崇阿里巴巴的技术&#xff0c;比如注册中心&#xff0c;SpringCloudAlibaba也推出了一个名为Nacos的注册中心。 ​ Nacos致力于帮助您发现、配置和管理微服务。Nacos提供了一组简单易用的特性集&#xff0c;帮助您实现动态服务发…

JVM笔记(4)—— 运行时数据区——堆空间

一、堆空间内存结构 堆空间内存分为年轻代和老年代。年轻代又细分为Eden区&#xff0c;Survivor1区和Survivor2区&#xff08;又称为from区和to区&#xff09; 为什么要对堆空间进行分代&#xff1f; 因为不同对象的生命周期不同&#xff0c;绝大部分对象都是临时对象&#x…

DIY 3D打印机——【有啥用啥版】

3D打印已经非常普及&#xff0c;手搓3D打印机的也很普遍了&#xff0c;不幸的是多年前买的三角洲&#xff08;delta型&#xff09;打印机年前罢工了&#xff0c;幸好它完成了一项重要使命&#xff1a;让手搓的铣床动起来&#xff0c;从而能够让铣床把受力部分的PLA零件自己加工…

高频卡顿问题分析

从监控图中可以看到&#xff0c;3.76k的用户&#xff0c;两分钟内报卡顿次数达到100万次 &#xff0c;很恐怖&#xff0c;这个是非正常的卡顿 由于没有日志&#xff0c;只能先看代码分析&#xff0c;出现高频卡顿的原因 问题描述 在播放过程&#xff0c;会频繁上报卡顿&…

Redis详解(二)

文章目录Redis的单线程模型Redis数据过期删除策略内存淘汰机制手写LRU持久化快照持久化(RDB)RDB优缺点AOF持久化AOF优缺点RDB和AOF的选择注意事项Redis修改配置后未生效(windows)Redis的单线程模型 Redis基于Reactor模式来设计开发了自己的一套高效的时间处理模型。 Redis内部…

leetcode-每日一题-1669-合并两个链表(中等,链表操作)

这道题就是考察对链表的理解&#xff0c;但是题目给的链表和我们数据结构学的还是有点不一样的&#xff0c;这里面的头节点是带节点信息的&#xff0c;我们按照课本来说的话头节点&#xff0c;或者叫首元节点如果我记得不错的话就是叫这个&#xff0c;是不提供节点信息的&#…

[数字媒体] PR视频剪辑之自定义音频、视频加速转场和特显停顿

这篇博客是作者数字媒体系列的笔记&#xff0c;仅作为在线笔记供大家学习。在剪辑视频中&#xff0c;我们会遇到自定义音频、视频加速转场、特显停顿、画面调整等技巧&#xff0c;这篇文章将详细介绍。希望对您有所帮助&#xff0c;后续有时间会深入分享视频制作、动画制作等内…

结合淘宝与Twitter详解分布式系统与其架构设计,分布式其实并不难,阿里架构师用实战给讲明白了!

什么是分布式架构 分布式系统&#xff08;distributed system&#xff09; 是建立在网络之上的软件系统。 内聚性&#xff1a;是指每一个数据库分布节点高度自治&#xff0c;有本地的数据库管理系统。 透明性&#xff1a;是指每一个数据库分布节点对用户的应用来说都是透明的…

手把手教你如何从0到1开发自动化测试框架,你确定不看?

目录 一、序言 二、自动化测试框架技术选型 三、自动化测试框架的设计思路 四、自动化框架介绍 五、框架技术要点解析 六、后续TODO 一、序言 随着项目版本的快速迭代、APP测试有以下几个特点&#xff1a; 首先&#xff0c;功能点多且细&#xff0c;测试工作量大&#x…

Redis基本通用命令

通用命令 查看使用文档&#xff0c;例如要查看select怎么使用 help select切换数据库 select 1查看符合模板的所有key keys * keys *a keys a*判断key是否存在 exists k1给key设置有效期&#xff0c;给k1设置20秒有效期 expire k1 20查看key剩余有效期&#xff0c;查看k1…

2014年408算法题

文章目录0 结果1 题目2 思路0 结果 1 题目 2 思路 二叉树的带权路径长度&#xff08;WPL&#xff09;的计算方法有两种&#xff1a; 1&#xff0c;定义&#xff1a;WPL所有叶结点的权值Wi∗该结点深度Di求和WPL所有叶结点的权值W_i*该结点深度D_i求和WPL所有叶结点的权值Wi​…

linux环境minio安装启动,管理员登录,nginx代理

一.下载minio 官网下载: MinIO | Code and downloads to create high performance object storage 直接点击下载或者用wget https://dl.min.io/server/minio/release/linux-amd64/minio 最后都是得到一个文件minio(大概100M) 二.启动minio 1.创建文件夹,比如 mkdir /data…