Spring框架中的Bean生命周期
目录
Bean的实例化
BeanFactoryPostProcessor
属性赋值
循环依赖
初始化
处理各种Aware接口
执行BeanPostProcessor前置处理
执行InitializingBean初始化方法或执行init-method自定义初始化方法
执行BeanPostProcessor后置处理
销毁
Spring Bean 的生命周期总体分为四个阶段:
- 实例化
- 属性赋值
- 初始化
- 销毁
Bean的实例化
Spring容器在进行初始化时,会将xml或者配置类中配置的相关的类通过Java Proxy(反射)的方式创建出一个BeanDefinition对象,然后将所有的BeanDefinition对象存在一个beanDefinitionMap的集合中去,xml中配置的bean的id或者注解配置的value属性作为存入Map的key,整个BeanDefinition对象作为value保存。
BeanFactoryPostProcessor
BeanFactoryPostProcessor是一个接口规范,实现了该接口的类只要交由Spring容器管理的话,那么 Spring就会回调该接口的方法,用于对BeanDefinition注册和修改的功能。如果实现了这个接口并在其中完成了一些BeanDefinition的注册或修改,那么在Bean真正实例化之前,会先回调这个接口的方法,执行其中的逻辑,如果没有实现该接口,那么完成真正的实例化。
属性赋值
BeanDefinition 中有对当前Bean实体的注入信息通过属性propertyValues进行了存储,Spring在进行属性注入时,会分为如下几种情况:
- 注入普通属性,String、int或存储基本类型的集合时,直接通过set方法的反射设置进去;
- 注入单向对象引用属性时,从容器中getBean获取后通过set方法反射设置进去,如果容器中没 有,则先创建被注入对象Bean实例(完成整个生命周期)后,在进行注入操作;
- 注入双向对象引用属性时,就比较复杂了,涉及了循环引用(循环依赖)
循环依赖
多个实体之间相互依赖并形成闭环的情况就叫做"循环依赖",也叫做“循环引用”,当一个Bean对象中如果引用了另一个Bean对象时,会暂停自己的初始化,先将引用的那个Bean对象先创建出来,然后再继续自己的初始化过程;但在这个过程中,可能会出现引用的那个Bean对象中也引用了引用它的Bean对象,这个时候就会产生循环依赖的情况。
为了解决循环依赖,Spring提供了三级缓存存储完整的Bean实例和半成品的Bean实例:
- 最终存储单例Bean成品的容器,即实例化和初始化都完成的Bean,称之为"一级缓存" Map singletonObjects = new ConcurrentHashMap(256);
- 早期Bean单例池,缓存半成品对象,且当前对象已经被其他对象引用了,称之为"二级缓存" Map earlySingletonObjects = new ConcurrentHashMap(16);
- 单例Bean的工厂池,缓存半成品对象,对象未被引用,使用时在通过工厂创建Bean,称之为"三 级缓存" Map> singletonFactories = new HashMap(16);
有了三级缓存的后,在属性赋值阶段会如果某个Bean中引用其他Bean,那么会依次从“三级缓存”往“一级缓存”中找,避免了循环依赖的问题。
初始化
经过Bean的实例化和属性赋值后的Bean其实还并不是一个完整的Bean实例对象,而是一个“半成品”,在完成它的初始化后才会成为一个完整的Bean实例对象并存放进到一个名为singletonObjects的Map中,最后当执行applicationContext.getBean(beanName)时,从singletonObjects去匹配Bean实例返回。
初始化的过程有以下几个关键点:
处理各种Aware接口
Aware接口是一种框架辅助属性注入的一种思想,为Bean生命周期各个阶段提供扩展。
- 如果Bean实现BeanNameAware接口,会调用它实现的setBeanName(String beanId)方法,注入Bean的名字;
- 如果Bean实现BeanClassLoaderAware接口,调用setBeanClassLoader()方法,注入ClassLoader对象的实例;
- 如果Bean实现BeanFactoryAware接口,会调用它实现的setBeanFactory()方法,注入的是Spring工厂;
- 如果Bean实现ApplicationContextAware接口,会调用setApplicationContext()方法,注入Spring上下文;
执行BeanPostProcessor前置处理
Bean被实例化后,到最终缓存到名为singletonObjects单例池之前,中间会经过Bean的初始化过程, 例如:属性的填充、初始方法init的执行等,其中有一个对外进行扩展的点BeanPostProcessor,我们称为Bean后 处理。跟Bean工厂后处理器相似,它也是一个接口,实现了该接口并被容器管理的BeanPostProcessor, 会在流程节点上被Spring自动调用。
执行InitializingBean初始化方法或执行init-method自定义初始化方法
- 如果Bean实现了InitializingBean接口,执行afeterPropertiesSet()方法。
- 如果Bean在Spring配置文件中配置了 init-method 属性,则会自动调用其配置的初始化方法。
执行BeanPostProcessor后置处理
如果这个Bean实现了BeanPostProcessor接口,将会调用postProcessAfterInitialization(Object obj, String s)方法,由于这个方法是在Bean初始化结束后调用;
在结束以上初始化的所有过程之后,就创建出了一个完整的Bean实例对象,我们就可以通过applicationContext.getBean(beanName)使用真正的Bean对象了。
销毁
销毁一个Bean对象有两种方式:
- 执行DisposableBean销毁Bean: 当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接口,会调用其实现的destroy()方法执行销毁;
- 执行destroy-method自定义销毁方法: 如果这个Bean的Spring配置中配置了destroy-method属性,会自动调用其配置的自定义销毁方法。
相关文章:
Spring框架中的Bean生命周期
目录 Bean的实例化 BeanFactoryPostProcessor 属性赋值 循环依赖 初始化 处理各种Aware接口 执行BeanPostProcessor前置处理 执行InitializingBean初始化方法或执行init-method自定义初始化方法 执行BeanPostProcessor后置处理 销毁 Spring Bean 的生命周期总体分为…...
async和await修饰符
async和await是JavaScript中用来处理异步操作的关键字 。 async和await也是解决回调地域的终极方案,简单,而Promise链混杂难以看懂。 async关键字用于定义一个函数,使其返回一个Promise对象。这意味着该函数可以通过await关键字来暂停执行&…...
vivado tcl创建工程和Git管理
一、Tcl工程创建 二、Git版本管理 对于创建完成的工程需要Git备份时,不需要上传完整几百或上G的工程,使用tcl指令创建脚本,并只将Tcl脚本上传,克隆时,只需要克隆tcl脚本,使用vivado导入新建工程即可。 优…...
田间农业数字管理系统-高标准农田建设
政策背景 2019年11月,国务院办公厅印发的《国务院办公厅关于切实加强高标准农田建设提升粮食安全保障能力的意见》明确提出,到2022年,全国要建成10亿亩高标准农田。 2021年9月16日,由农业农村部印发的《全国高标准农田建设规划&a…...
【网络安全】等保测评系列预热
【网络安全】等保测评系列预热 前言1. 什么是等级保护?2. 为什么要做等保?3. 路人甲疑问? 一、等保测试1. 渗透测试流程1.1 明确目标1.2 信息搜集1.3 漏洞探索1.4 漏洞验证1.5 信息分析1.6 获取所需1.7 信息整理1.8 形成报告 2. 等保概述2.1 …...
解决: git拉取报错 git 未能顺利结束 (退出码 1)
拉取代码失败信息 解决方法: 执行一下"git push -f origin master"命令即可 步骤: 1.项目文件夹右击选择"Git Bash Here",打开命令窗口 2. 输入"git push -f origin master"后,回画 执行结束 3.再拉取代码,成功...
【深度学习中的批量归一化BN和层归一化LN】BN层(Batch Normalization)和LN层(Layer Normalization)的区别
文章目录 1、概述2、BN层3、LN层4、Pytorch的实现5、BN层和LN层的对比 1、概述 归一化(Normalization) 方法:指的是把不同维度的特征(例如序列特征或者图像的特征图等)转换为相同或相似的尺度范围内的方法,比如把数据特征映射到[…...
开发一个RISC-V上的操作系统(六)—— 中断(interrupt)和异常(exception)
目录 往期文章传送门 一、控制流 (Control Flow)和 Trap 二、Exceptions, Traps, and Interrupts Contained Trap Requested Trap Invisible Trap Fatal Trap 异常和中断的异同 三、RISC-V的异常处理 mtvec(Machine Trap-Vector Ba…...
心跳跟随的心形灯(STM32(HAL)+WS2812+MAX30102)
文章目录 前言介绍系统框架原项目地址本项目开发开源地址硬件PCB软件功能 详细内容硬件外壳制作WS2812级联及控制MAX30102血氧传感器0.96OLEDFreeRTOS 效果视频总结 前言 在好几年前,我好像就看到了焊武帝 jiripraus在纪念结婚五周年时,制作的一个心跳跟…...
5. 服务发现
当主机较少时,在抓取配置中手动列出它们的IP地址和端口是常见的做法,但不适用于较大规模的集群。尤其不适用使用容器和基于云的实例的动态集群,这些实例经常会变化、创建或销毁的情况。 Prometheus通过使用服务发现解决了这个问题࿱…...
算法备案背后的原因:确保技术透明度与公正
随着现代技术的发展,算法逐渐渗透到我们日常生活的各个方面,从金融决策到个性化的商品推荐,再到医疗诊断和司法系统。然而,这种无所不在的应用也带来了一系列的社会和伦理问题,尤其是在算法的透明度和公正性上。这正是…...
Linux centos 常用命令 【持续更新】
一、查看文件信息 indoe和目录项 # df命令查看每个硬盘分区的inode总数和已经使用的数量 df -i# 查看inode的大学 xfs_growfs /dev/sda1|grep "isize"# 查看文件的indoe号码 ls -istat查看文件信息 # 文件的详细信息 stat anaconda-ks.cfg # -t参数是在一行内输出…...
《使用 VMware 在 Windows 上搭建 Linux 系统的完整指南》
《使用 VMware 在 Windows 上搭建 Linux 系统的完整指南》 1、准备工作1.1 安装 VMware 软件1.2 下载 Linux 发行版镜像文件1.3 安装SSH工具 2、创建新的虚拟机2.1 VMware页面2.2 打开VMware页面并点击创建新的虚拟机,选择自定义2.3 选择系统兼容性,默认…...
大数据Flink(六十):Flink 数据流和分层 API介绍
文章目录 Flink 数据流和分层 API介绍 一、Flink 数据流...
软件测试面试题——如何测试App性能?
为什么要做App性能测试? 如果APP总是出现卡顿或网络延迟的情况,降低了用户的好感,用户可能会抛弃该App,换同类型的其他应用。如果APP的性能较好,用户体验高,使用起来丝滑顺畅,那该应用的用户粘…...
玩转C链表
链表是C语言编程中常用的数据结构,比如我们要建一个整数链表,一般可能这么定义: struct int_node {int val;struct int_node *next;}; 为了实现链表的插入、删除、遍历等功能,另外要再实现一系列函数,比如:…...
MySQL表的基础的增删改查
增(insert into) 插入所有列的数据 不写具体列名要确保字段都对应正确 -- 假设你有一个名为 "employees" 的表,有多个列 INSERT INTO employees VALUES (101, Alice, Manager, 50000);插入指定列的数据 -- 假设你有一个名为 "students" 的表&…...
数字化车间
一、数字化车间概述 数字化车间是以现代化信息、网络、数据库、自动识别等技术为基础,通过智能化、数字化、MES系统信息化等手段融合建设的数字化生产车间,精细地管理生产资源、生产设备和生产过程。随着工业4.0概念的提出,未来的工业和制造…...
基础堆排序
目录 基础堆排序 一、概念及其介绍 二、适用说明 三、过程图示 基础堆排序...
ISC 2023 | 赛宁网安验证评估 重磅发布
8月9日-10日,第十一届互联网安全大会(简称ISC 2023)在北京国家会议中心隆重举办。作为本次大会的战略合作伙伴(最高级别),赛宁网安主办 “安全验证评估论坛”,邀请邬江兴院士与业界专家共同…...
C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...
线程同步:确保多线程程序的安全与高效!
全文目录: 开篇语前序前言第一部分:线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分:synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分ÿ…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)
设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile,新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...
基于 TAPD 进行项目管理
起因 自己写了个小工具,仓库用的Github。之前在用markdown进行需求管理,现在随着功能的增加,感觉有点难以管理了,所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD,需要提供一个企业名新建一个项目&#…...
