当前位置: 首页 > news >正文

Spring Bean 的生命周期了解么?

Spring Bean 的生命周期基本流程

一个Spring的Bean从出生到销毁的全过程就是他的整个生命周期,

img

整个生命周期可以大致分为3个大的阶段 :

  • 创建

  • 使用

  • 销毁

还可以分为5个小步骤 :

实例化(Bean的创建) , 初始化赋值, 注册Destruction回调 , Bean的正常使用 以及 Bean的销毁

Bean的创建和初始化赋值是分开的

具体代码实现 :

Spring容器在进行实例化的时候,会将xml配置的< bean > 的信息封装成一个BeanDefinition对象, Spring根据BeanDefinition来创建Bean对象,里面有很多的属性来描述Bean

  • beanClassName : bean的类名

  • initMethodName : 初始化方法名称

  • properryValues : bean的属性值

  • scope : 作用域

  • lazyInit : 延迟初始化

  1. 实例化Bean(实例化阶段)

    • Spring容器首先创建Bean实例

    • 调用Bean的构造函数,来实例化Bean对象

      • Spring在这一步创建Bean实例。 主要代码在AbstractAutowireCapableBeanFactory类中的createBeanInstance方法中实现

        就是先确保这个Bean对应的类已经被加载,然后确保他是public的,然后如果有工厂方法,则直接调用工厂方法创建Bean,如果没有的话就调用它的构造方法来创建这个Bean.

        这里需要注意的是 ,在Spring的完整Bean创建和初始化流程中,容器会在调用createBeanInstance之前检查Bean定义的作用域。如果是Singleton,容器会在其内部单例缓存中查找现有实例。如果实例已经存在,他将被重用;如果不存在,才会调用createBeanInstance来创建新的实例;

  2. (依赖注入)设置属性值(初始化阶段)

    • Spring容器注入必要的属性到Bean中

      • populateBean方法是Spring Bean生命周期中的一个关键部分,负责将属性值应用到新创建的Bean实例。他处理了自动装配,属性注入,依赖检查等多个方面 . 就是把各种属性进行初始化

  3. 检查Aware

    • 如果Bean实现了BeanNameAware , BeanClassLoaderAware等这些Aware接口, Spring容器会调用它们

      • BeanNameAware :通过这个接口,Bean可以获取到自己在Spring容器中的名字。这对于需要根据Bean的名称某些操作的常见很有用

      • ApplicationContextAware: 获取ApplicationContext对象;

      • BeanFactoryAware : 通过这个接口可以获取对BeanFactory的引用,获得对BeanFactory的访问权限

  4. 调用BeanPostProcessor前置处理方法 (初始化之前进行回调)

    • 在Bean初始化之前, 允许自定义的BeanPostProcessor对Bean实例进行处理,如修改Bean的状态. BeanPostProcessor的postProcessBeforeInitialization方法会在此时被调用

  5. 执行初始化方法

    1. 调用InitializingBean的afterPropertiesSet方法

      • 提供一个机会, 在所有Bean属性设置完成后进行初始化操作, 如果Bean实现了InitializingBean接口, afterPropertiesSet方法会被调用

      • 主要作用就是帮助我们在Bean的初始化前添加一些自己的逻辑处理,Spring内置了很多BeanPostProcessor,我们也可以定义一个或者多个BeanPostProcessor接口的实现,然后注册到容器中;

    2. 调用自定义init-method方法(初始化方法)

      • 提供一种配置方式, 在xml配置中指定Bean的初始化方法. 如果Bean在配置文件中定义了初始化方法,那么该方法就会被调用

  6. 调用BeanPostProcessor的后置处理方法 (Spring中对类进行增强的时候(AOP),就会使用后置处理器) --> AOP底层使用了动态代理和CGLB动态代理

    • 在Bean初始化之后,再次允许BeanPostProcessor对Bean进行处理. BeanPostProcessor的postProcessAfterInitialization方法会在此时被调用

  7. 注册Destruction回调

    • 如果Bean实现了DIsposableBean接口或者bean定义中指定了自定义的销毁方法,Spring容器会为这些Bean注册一个销毁回调,确保在容器关闭的时候能够正确的清理资源

  8. Bean准备就绪(Bean的使用阶段)

    • 此时,Bean已经完全初始化,可以开始处理应用程序的请求了

  9. 调用DisposableBean的destroy方法(Bean的销毁阶段)

    • 当容器关闭的时候, 如果Bean实现了DisposableBean接口, destroy方法会被调用

    • 在DisposableBeanAdapter的destroy方法中实现

  10. 调用自定义的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勒索病毒数据怎么处理|数据解密恢复

导言&#xff1a; 随着网络安全威胁的不断增加&#xff0c;勒索软件已成为严重的威胁之一&#xff0c;.ryabina勒索病毒是其中之一。本文将介绍.ryabina勒索病毒的特点、数据恢复方法和预防措施&#xff0c;以帮助用户更好地应对这一威胁。当面对被勒索病毒攻击导致的数据文件…...

上网行为监控软件能够看到聊天内容吗

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

Java知识点一

hello&#xff0c;大家好&#xff01;我们今天开启Java语言的学习之路&#xff0c;与C语言的学习内容有些许异同&#xff0c;今天我们来简单了解一下Java的基础知识。 一、数据类型 分两种&#xff1a;基本数据类型 引用数据类型 &#xff08;1&#xff09;整型 八种基本数…...

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(最近最少使用)缓存结构&#xff0c;该结构在构造时确定大小&#xff0c;假设大小为 capacity &#xff0c;操作次数是 n &#xff0c;并有如下功能: Solution(int capacity) 以正整数作为容量 capacity 初始化 LRU 缓存get(key)&#xff1a;如果关键字 key …...

论文阅读——ONE-PEACE

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

围剿尚未终止 库迪深陷瑞幸9.9阳谋

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

5G网络(接入网+承载网+核心网)

5G网络&#xff08;接入网承载网核心网&#xff09; 一、5G网络全网架构图 这张图分为左右两部分&#xff0c;右边为无线侧网络架构&#xff0c;左边为固定侧网络架构。 无线侧&#xff1a;手机或者集团客户通过基站接入到无线接入网&#xff0c;在接入网侧可以通过RTN或者IP…...

学习Markdown

https://shadows.brumm.af 欢迎使用Markdown编辑器 你好&#xff01; 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章&#xff0c;了解一下Markdown的基本语法知识。 新的改变 我们对Markdown编辑器进行了一些…...

MySQL知识点总结(五)——锁

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

IDEA 2023.2 配置 JavaWeb 工程

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

软考40-上午题-【数据库】-关系代数运算2-专门的集合运算

一、专门的集合运算 1、投影 示例&#xff1a; 可以用属性名进行投影&#xff0c;也可以用列的序号进行投影。 2、选择 例题 1、笛卡尔积 2、投影 3、选择 3、连接 第一步都要算&#xff1a;笛卡尔积。 3-1、θ连接 示例&#xff1a; 3-2、等值连接 示例&#xff1a; 3-3、自…...

RHEL9安装Python2.7

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

更新至2022年世界各国数字经济发展相关指标(23个指标)

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

vue从flask获取数据并显示

记录一个前后端分离遇到的问题&#xff0c;即vue前端从flask后端获取数据。具体描述如下&#xff1a;flask只负责连接数据库并获取数据库的数据&#xff0c;并返回给前端vue&#xff1b;vue则需要获取后端返回的数据并显示。 方法如下&#xff0c;分别用一个vue组件和一个flas…...

Kafka生产常见问题分析与总结

Kafka生产常见问题分析与总结 消息丢失 生产者 acks 0 不需要等待任何Broker确认收到消息的回复就可以继续发消息 性能最高&#xff0c;但是最容易丢消息&#xff0c;对于数据丢失不敏感的场景可以使用&#xff0c;如大数据统计报表 acks 1 只要等待Broker中的leader成功写…...

重温MySQL

mysql 是什么 mysql 就是一个软件,专门用来管理文件的软件 关系型数据库:采用二维表结构组织和管理数据,并且规定了表和表间数据的关系. 表是由行和列构成,列包含一组命名的属性(也称字段),行包含一条记录.行和列的交集称为数据项 (也称字段值). 如何操作数据库 那就是用sq…...

构造函数,原型,实例,类的关系整理

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

[极客挑战2019]HTTP

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

国防科技大学计算机基础课程笔记02信息编码

1.机内码和国标码 国标码就是我们非常熟悉的这个GB2312,但是因为都是16进制&#xff0c;因此这个了16进制的数据既可以翻译成为这个机器码&#xff0c;也可以翻译成为这个国标码&#xff0c;所以这个时候很容易会出现这个歧义的情况&#xff1b; 因此&#xff0c;我们的这个国…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索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智慧点检验收套件

在选煤厂、化工厂、钢铁厂等过程生产型企业&#xff0c;其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进&#xff0c;需提前预防假检、错检、漏检&#xff0c;推动智慧生产运维系统数据的流动和现场赋能应用。同时&#xff0c;…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; 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 到镜舟数据库:杭银消费金融湖仓一体转型实践

作者&#xff1a;吴岐诗&#xff0c;杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言&#xff1a;融合数据湖与数仓的创新之路 在数字金融时代&#xff0c;数据已成为金融机构的核心竞争力。杭银消费金…...