Spring Bean 的生命周期了解么?
Spring Bean 的生命周期基本流程
一个Spring的Bean从出生到销毁的全过程就是他的整个生命周期,
整个生命周期可以大致分为3个大的阶段 :
-
创建
-
使用
-
销毁
还可以分为5个小步骤 :
实例化(Bean的创建) , 初始化赋值, 注册Destruction回调 , Bean的正常使用 以及 Bean的销毁
Bean的创建和初始化赋值是分开的
具体代码实现 :
Spring容器在进行实例化的时候,会将xml配置的< bean > 的信息封装成一个BeanDefinition对象, Spring根据BeanDefinition来创建Bean对象,里面有很多的属性来描述Bean
-
beanClassName : bean的类名
-
initMethodName : 初始化方法名称
-
properryValues : bean的属性值
-
scope : 作用域
-
lazyInit : 延迟初始化
-
实例化Bean(实例化阶段)
-
Spring容器首先创建Bean实例
-
调用Bean的构造函数,来实例化Bean对象
-
Spring在这一步创建Bean实例。 主要代码在AbstractAutowireCapableBeanFactory类中的createBeanInstance方法中实现
就是先确保这个Bean对应的类已经被加载,然后确保他是public的,然后如果有工厂方法,则直接调用工厂方法创建Bean,如果没有的话就调用它的构造方法来创建这个Bean.
这里需要注意的是 ,在Spring的完整Bean创建和初始化流程中,容器会在调用createBeanInstance之前检查Bean定义的作用域。如果是Singleton,容器会在其内部单例缓存中查找现有实例。如果实例已经存在,他将被重用;如果不存在,才会调用createBeanInstance来创建新的实例;
-
-
-
(依赖注入)设置属性值(初始化阶段)
-
Spring容器注入必要的属性到Bean中
-
populateBean方法是Spring Bean生命周期中的一个关键部分,负责将属性值应用到新创建的Bean实例。他处理了自动装配,属性注入,依赖检查等多个方面 . 就是把各种属性进行初始化
-
-
-
检查Aware
-
如果Bean实现了BeanNameAware , BeanClassLoaderAware等这些Aware接口, Spring容器会调用它们
-
BeanNameAware :通过这个接口,Bean可以获取到自己在Spring容器中的名字。这对于需要根据Bean的名称某些操作的常见很有用
-
ApplicationContextAware: 获取ApplicationContext对象;
-
BeanFactoryAware : 通过这个接口可以获取对BeanFactory的引用,获得对BeanFactory的访问权限
-
-
-
调用BeanPostProcessor前置处理方法 (初始化之前进行回调)
-
在Bean初始化之前, 允许自定义的BeanPostProcessor对Bean实例进行处理,如修改Bean的状态. BeanPostProcessor的postProcessBeforeInitialization方法会在此时被调用
-
-
执行初始化方法
-
调用InitializingBean的afterPropertiesSet方法
-
提供一个机会, 在所有Bean属性设置完成后进行初始化操作, 如果Bean实现了InitializingBean接口, afterPropertiesSet方法会被调用
-
主要作用就是帮助我们在Bean的初始化前添加一些自己的逻辑处理,Spring内置了很多BeanPostProcessor,我们也可以定义一个或者多个BeanPostProcessor接口的实现,然后注册到容器中;
-
-
调用自定义init-method方法(初始化方法)
-
提供一种配置方式, 在xml配置中指定Bean的初始化方法. 如果Bean在配置文件中定义了初始化方法,那么该方法就会被调用
-
-
-
调用BeanPostProcessor的后置处理方法 (Spring中对类进行增强的时候(AOP),就会使用后置处理器) --> AOP底层使用了动态代理和CGLB动态代理
-
在Bean初始化之后,再次允许BeanPostProcessor对Bean进行处理. BeanPostProcessor的postProcessAfterInitialization方法会在此时被调用
-
-
注册Destruction回调
-
如果Bean实现了DIsposableBean接口或者bean定义中指定了自定义的销毁方法,Spring容器会为这些Bean注册一个销毁回调,确保在容器关闭的时候能够正确的清理资源
-
-
Bean准备就绪(Bean的使用阶段)
-
此时,Bean已经完全初始化,可以开始处理应用程序的请求了
-
-
调用DisposableBean的destroy方法(Bean的销毁阶段)
-
当容器关闭的时候, 如果Bean实现了DisposableBean接口, destroy方法会被调用
-
在DisposableBeanAdapter的destroy方法中实现
-
-
调用自定义的destroy-method 当容器要进行关闭的时候,对象就会进入销毁阶段 ,最典型的就是,如果你使用了@PreDestroy注解,这个方法就是销毁方法 , Spring容器关闭的时候就会调用这个自定义的销毁方法
-
如果Bean在配置文件中定义了销毁方法, 那么该方法就会被调用
-
在DisposableBeanAdapter的destroy方法中实现
-
可以看到, 整个Bean的创建的过程都依赖于AbstractAutowireCapableBeanFactory这个类,而销毁主要依赖于DisposableBeanAdapter这个类
代码实践
package com.sfx.spring6;import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;/*** Created with IntelliJ IDEA.* Description:* User: sfx* Date: 2024-02-20* Time: 21:20*/
public class CatDog implements BeanNameAware, InitializingBean, DisposableBean {private String name;public CatDog() {System.out.println("1. 实例化Bean");}public String getName() {return name;}public void setName(String name) {System.out.println("2. 执行了set方法, 设置相关属性");this.name = name;}public void myInit() {System.out.println("6. 执行了自定义初始化方法");}public void myDestroy() {System.out.println("10. 执行了自定义的销毁方法");}@Overridepublic void setBeanName(String name) {System.out.println("3. 执行了 BeanNameAware");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("5. 执行afterPropertiesSet");}@Overridepublic void destroy() throws Exception {System.out.println("9. 执行了DisposableBean");}
}
package com.sfx.spring6;import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;/*** Created with IntelliJ IDEA.* Description:* User: sfx* Date: 2024-02-20* Time: 21:20*/
public class CatDog implements BeanNameAware, InitializingBean, DisposableBean {private String name;public CatDog() {System.out.println("1. 实例化Bean");}public String getName() {return name;}public void setName(String name) {System.out.println("2. 执行了set方法, 设置相关属性");this.name = name;}public void myInit() {System.out.println("6. 执行了自定义初始化方法");}public void myDestroy() {System.out.println("10. 执行了自定义的销毁方法");}@Overridepublic void setBeanName(String name) {System.out.println("3. 执行了 BeanNameAware");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("5. 执行afterPropertiesSet");}@Overridepublic void destroy() throws Exception {System.out.println("9. 执行了DisposableBean");}
}
package com.sfx.spring6;import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** Created with IntelliJ IDEA.* Description:* User: sfx* Date: 2024-02-20* Time: 21:23*/
public class App {public static void main(String[] args) {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");CatDog bean = applicationContext.getBean(CatDog.class);String name = bean.getName();System.out.println("8. 使用了Bean , " + name);((ClassPathXmlApplicationContext) applicationContext).close();}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 在spring中创建对象 --><!-- 配置 dog 这个Bean--><bean id = "catDog" class="com.sfx.spring6.CatDog" init-method="myInit" destroy-method="myDestroy"><property name="name" value="张三"></property></bean><bean id="processor" class="com.sfx.spring6.Processor"></bean></beans>
项目中会用到哪些流程呢 ?
我们在项目中一般等到项目初始化完成后立马执行一些动作, 比如RocketMQ开启消费者,还有等等我们需要在项目初始化完成之后就要执行一些动作,我们就可以调用 InitializingBean 的afterPropertiesSet方法
好的记忆方法
我们可以给面试官这么讲解, SpringBean的生命周期分为三个大的阶段
- 创建
- 使用
- 销毁
如果划分为具体的细的5个阶段 :
- 实例化
- 初始化(依赖注入)
- 注册Destruction的回调
- Bean的使用
- Bean的销毁
然后我们再来了解每一个阶段都要做哪些事情
- 实例化
- 首先会根据扫描我们写的xml,将一些属性设置到BeanDefination对象上,然后调用构造方法创建出一个Bean
- 初始化
- 给Bean设置属性(此时会调用bean的set方法)
- 检查有没有实现以aware结尾的相关接口
-
BeanNameAware :通过这个接口,Bean可以获取到自己在Spring容器中的名字。这对于需要根据Bean的名称某些操作的常见很有用
-
ApplicationContextAware: 获取ApplicationContext对象;
-
BeanFactoryAware : 通过这个接口可以获取对BeanFactory的引用,获得对BeanFactory的访问权限
-
-
执行初始化前置方法
-
执行初始化方法 (有两个, 首先先会调用 InitializingBean 的afterPropertiesSet方法,然后会调用自己定义的初始化方法)
-
执行初始化后置方法
-
注册Destruction的回调
-
如果Bean实现了DIsposableBean接口或者bean定义中指定了自定义的销毁方法,Spring容器会为这些Bean注册一个销毁回调,确保在容器关闭的时候能够正确的清理资源
-
-
开始使用Bean
-
调用DisposableBean的destroy方法(Bean的销毁阶段)
-
当容器关闭的时候, 如果Bean实现了DisposableBean接口, destroy方法会被调用
-
在DisposableBeanAdapter的destroy方法中实现
-
-
调用自定义的destroy-method 当容器要进行关闭的时候,对象就会进入销毁阶段 ,最典型的就是,如果你使用了@PreDestroy注解(对于SpringBoot),这个方法就是销毁方法 , Spring容器关闭的时候就会调用这个自定义的销毁方法
-
如果Bean在配置文件中定义了销毁方法, 那么该方法就会被调用
-
在DisposableBeanAdapter的destroy方法中实现
-
对于SpringBoot而言,如果你想要在实例化和依赖注入完成后进行初始化操作,可以加@PostConstruct注解 ,当然也可以使用 InitializingBean 的afterPropertiesSet方法
如果你想要自定义销毁方法 , 可以加 @PreDestroy注解
下次分享再见~~~
相关文章:

Spring Bean 的生命周期了解么?
Spring Bean 的生命周期基本流程 一个Spring的Bean从出生到销毁的全过程就是他的整个生命周期, 整个生命周期可以大致分为3个大的阶段 : 创建 使用 销毁 还可以分为5个小步骤 : 实例化(Bean的创建) , 初始化赋值, 注册Destruction回调 , Bean的正常使用 以及 Bean的销毁 …...
.ryabina勒索病毒数据怎么处理|数据解密恢复
导言: 随着网络安全威胁的不断增加,勒索软件已成为严重的威胁之一,.ryabina勒索病毒是其中之一。本文将介绍.ryabina勒索病毒的特点、数据恢复方法和预防措施,以帮助用户更好地应对这一威胁。当面对被勒索病毒攻击导致的数据文件…...

上网行为监控软件能够看到聊天内容吗
随着信息技术的不断发展,上网行为监控软件在企业网络安全管理中扮演着越来越重要的角色。 这类软件主要用于监控员工的上网行为,以确保工作效率和网络安全。 而在这其中,域智盾软件作为一款知名的上网行为监控软件,其功能和使用…...

Java知识点一
hello,大家好!我们今天开启Java语言的学习之路,与C语言的学习内容有些许异同,今天我们来简单了解一下Java的基础知识。 一、数据类型 分两种:基本数据类型 引用数据类型 (1)整型 八种基本数…...

Django学习笔记-forms使用
1.创建forms.py文件,导入包 from django import forms from django.forms import fields from django.forms import widgets2. 创建EmployeeForm,继承forms.Form 3.创建testform.html文件 4.urls.py添加路由 5.views中导入forms 创建testform,编写代码 1).如果请求方式为GET,…...
BM100 设计LRU缓存结构(java实现)
一、题目 设计LRU(最近最少使用)缓存结构,该结构在构造时确定大小,假设大小为 capacity ,操作次数是 n ,并有如下功能: Solution(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存get(key):如果关键字 key …...

论文阅读——ONE-PEACE
ONE-PEACE: EXPLORING ONE GENERAL REPRESENTATION MODEL TOWARD UNLIMITED MODALITIES 适应不同模态并且支持多模态交互。 预训练任务不仅能提取单模态信息,还能模态间对齐。 预训练任务通用且直接,使得他们可以应用到不同模态。 各个模态独立编码&am…...

围剿尚未终止 库迪深陷瑞幸9.9阳谋
文|智能相对论 作者|霖霖 总能被“累了困了”的打工人优先pick的咖啡,刚复工就顺利站上话题C位。 #瑞幸9.9元一杯活动缩水#的话题才爬上新浪微博热搜,“库迪咖啡河北分公司运营总监带头坑害河北联营商”的实名举报帖就出现在了小红书,一时…...

5G网络(接入网+承载网+核心网)
5G网络(接入网承载网核心网) 一、5G网络全网架构图 这张图分为左右两部分,右边为无线侧网络架构,左边为固定侧网络架构。 无线侧:手机或者集团客户通过基站接入到无线接入网,在接入网侧可以通过RTN或者IP…...
学习Markdown
https://shadows.brumm.af 欢迎使用Markdown编辑器 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。 新的改变 我们对Markdown编辑器进行了一些…...

MySQL知识点总结(五)——锁
MySQL知识点总结(五)——锁 锁分类表锁 & 行锁如何添加表锁?如何添加行锁? 读锁 & 写锁行锁 & 间隙锁(gap lock)& 临键锁(next-key lock) 加锁机制分析可重复读隔离…...

IDEA 2023.2 配置 JavaWeb 工程
目录 1 不使用 Maven 创建 JavaWeb 工程 1.1 新建一个工程 1.2 配置 Tomcat 1.3 配置模块 Web 2 使用 Maven 配置 JavaWeb 工程 2.1 新建一个 Maven 工程 2.2 配置 Tomcat 💥提示:IDEA 只有专业版才能配置 JavaWeb 工程,若是社区版&am…...

软考40-上午题-【数据库】-关系代数运算2-专门的集合运算
一、专门的集合运算 1、投影 示例: 可以用属性名进行投影,也可以用列的序号进行投影。 2、选择 例题 1、笛卡尔积 2、投影 3、选择 3、连接 第一步都要算:笛卡尔积。 3-1、θ连接 示例: 3-2、等值连接 示例: 3-3、自…...

RHEL9安装Python2.7
RHEL9作为2022年5月新推出的版本,较RHEL8有了很多地方的改进,而且自带很多包,功能非常强大,稳定性和流畅度也较先前版本有了很大的提升。RHEL9自带python3.9,但是过高版本的python不可避免地会导致一些旧版本包地不兼容…...

更新至2022年世界各国数字经济发展相关指标(23个指标)
更新至2022年世界各国数字经济发展相关指标(23个指标) 1、时间:具体指标时间见下文 2、来源:WDI、世界银行、WEF、UNCTAD、SJR、国际电联 3、指标:移动网络覆盖率(2000-2022)、固定电话普及率…...

vue从flask获取数据并显示
记录一个前后端分离遇到的问题,即vue前端从flask后端获取数据。具体描述如下:flask只负责连接数据库并获取数据库的数据,并返回给前端vue;vue则需要获取后端返回的数据并显示。 方法如下,分别用一个vue组件和一个flas…...
Kafka生产常见问题分析与总结
Kafka生产常见问题分析与总结 消息丢失 生产者 acks 0 不需要等待任何Broker确认收到消息的回复就可以继续发消息 性能最高,但是最容易丢消息,对于数据丢失不敏感的场景可以使用,如大数据统计报表 acks 1 只要等待Broker中的leader成功写…...
重温MySQL
mysql 是什么 mysql 就是一个软件,专门用来管理文件的软件 关系型数据库:采用二维表结构组织和管理数据,并且规定了表和表间数据的关系. 表是由行和列构成,列包含一组命名的属性(也称字段),行包含一条记录.行和列的交集称为数据项 (也称字段值). 如何操作数据库 那就是用sq…...

构造函数,原型,实例,类的关系整理
视频来源js原型链、构造函数和类_哔哩哔哩_bilibili 如视频所说,构造函数的prototype指向原型,实例化的对象的__proto__指向原型,原型通过constructor指向构造函数,正如class里面的constructor方法就相当于Person构造函数一样&am…...

[极客挑战2019]HTTP
这道题考察的是http请求头字段的含义和使用; 具体如下 Referer:来源地址 User-Agent:客户端配置信息:浏览器类型、版本、系统类型等 X-Forwarded-For:代理地址,即数据发出的地址 开始解题:(对我这初学者真的烧脑&a…...

国防科技大学计算机基础课程笔记02信息编码
1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制,因此这个了16进制的数据既可以翻译成为这个机器码,也可以翻译成为这个国标码,所以这个时候很容易会出现这个歧义的情况; 因此,我们的这个国…...
Vue记事本应用实现教程
文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展:显示创建时间8. 功能扩展:记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...

全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
关于 WASM:1. WASM 基础原理
一、WASM 简介 1.1 WebAssembly 是什么? WebAssembly(WASM) 是一种能在现代浏览器中高效运行的二进制指令格式,它不是传统的编程语言,而是一种 低级字节码格式,可由高级语言(如 C、C、Rust&am…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...
在Ubuntu24上采用Wine打开SourceInsight
1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践
作者:吴岐诗,杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言:融合数据湖与数仓的创新之路 在数字金融时代,数据已成为金融机构的核心竞争力。杭银消费金…...