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…...
SkyWalking 10.2.0 SWCK 配置过程
SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外,K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案,全安装在K8S群集中。 具体可参…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...

(转)什么是DockerCompose?它有什么作用?
一、什么是DockerCompose? DockerCompose可以基于Compose文件帮我们快速的部署分布式应用,而无需手动一个个创建和运行容器。 Compose文件是一个文本文件,通过指令定义集群中的每个容器如何运行。 DockerCompose就是把DockerFile转换成指令去运行。 …...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...
SpringAI实战:ChatModel智能对话全解
一、引言:Spring AI 与 Chat Model 的核心价值 🚀 在 Java 生态中集成大模型能力,Spring AI 提供了高效的解决方案 🤖。其中 Chat Model 作为核心交互组件,通过标准化接口简化了与大语言模型(LLM࿰…...