SpringBoot中bean的生命周期

文章目录

  • 概述
  • 使用场景
  • 代码演示bean初始化
    • TestSupport
    • BeanPostProcessorImpl
    • log
  • 代码

概述

Bean 生命周期管理是 Spring Boot 中的关键功能之一。它负责管理应用程序中的 Java 对象,这些对象被称为 Beans。Spring Boot 通过创建、配置、初始化和销毁这些 Beans 来确保应用程序的正常运行。这个功能的目的是提供一种灵活的方式,使开发人员能够轻松地管理对象的生命周期,从而实现高效的依赖注入和组件化开发。

在这里插入图片描述

1、实例化:在 Spring 容器启动时,Spring 会创建配置中定义的所有 Bean。这是通过 Java 类的构造函数或工厂方法来完成的。

2、属性注入:一旦 Bean 被实例化,Spring 会注入所有相关的属性,包括通过构造函数注入或 Setter 方法注入的属性。

3、初始化方法调用:一旦属性被注入,Spring 容器会调用 Bean 的初始化方法。这可以通过@PostConstruct注解、实现InitializingBean接口来完成。初始化过程还提供了一些扩展口:BeanNameAware,BeanFactoryAware,ApplicationContextAware

4、使用 Bean:Bean 现在可以在应用程序中使用,执行其业务逻辑。

5、销毁方法调用:当 Spring 容器关闭时,它会调用 Bean 的销毁方法以释放资源。这可以通过@PreDestroy注解、实现DisposableBean接口来完成。

使用场景

  • 依赖注入:当你需要将一个对象注入到另一个对象中时,Bean 的生命周期管理可以确保被注入的对象已正确初始化。
  • 配置管理:如果你希望根据不同的环境或配置文件来配置 Bean 的属性,Bean 的生命周期管理可以帮助你实现这一目标。
  • 组件扩展:当你需要创建自定义的 Bean,以扩展 Spring Boot 的功能时,Bean 的生命周期管理可以为你提供扩展点。
  • 切面编程:可以在生命周期中预埋代码实现切面编程。例如SpringBoot AOP代理类的实现。

代码演示bean初始化

编写代码演示bean初始化各个节点。

演示代码将创建以下类:

  • TestSupport:一个普通的组件,将作为被观测对象
  • BeanPostProcessorImpl:BeanPostProcessor接口的实现类,用于实现postProcessBeforeInitialization 和postProcessAfterInitialization 并观测TestSupport对象

TestSupport

import com.alibaba.fastjson2.JSON;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;@Slf4j
@RequiredArgsConstructor
@Component
public class TestSupport implements BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean {private final ApplicationContext  applicationContext;@Overridepublic void setBeanName(String s) {log.info("TestSupport-BeanNameAware-setBeanName.param={}", s);}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {log.info("TestSupport-BeanFactoryAware-setBeanFactory.param={}", "beanFactory");}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {log.info("TestSupport-ApplicationContextAware-setApplicationContext.param={}", JSON.toJSONString(applicationContext.getId()));}@Overridepublic void afterPropertiesSet() throws Exception {log.info("TestSupport-InitializingBean-afterPropertiesSet");}@PostConstructpublic void InitSomething() {log.info("通过 @PostConstruct 注解执行自定义初始化逻辑");}
}
  • BeanNameAware:通过实现BeanNameAware接口并重写setBeanName方法可以获取到bean的name
  • BeanFactoryAware:通过实现BeanFactoryAware接口并重写setBeanFactory方法可以在bean初始化过程中添加额外的扩展,比如可以通过判断beanFactory.alreadyCreated中是否有某bean而做一些不同的操作
  • ApplicationContextAware:通过实现ApplicationContextAware接口并重写setApplicationContext方法可以在bean初始化过程中添加额外扩展。
  • InitializingBean:通过实现InitializingBean接口并重写afterPropertiesSet 方法可以在bean初始化过程中添加额外扩展。比如将此bean存入map中以备它用
  • @PostConstruct:此外还可以通过在方法上面添加@PostConstruct注解来执行一些自定义的业务代码

BeanPostProcessorImpl

import com.ramble.beanlife.support.TestSupport;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class BeanPostProcessorImpl implements BeanPostProcessor {/*** bean 加工器之在bean实例化之前得预处理* 这个处理类针对所有得bean,所以如果需要对特定得bean做处理需要通过 beanName.equals("testSupport")  或者  bean instanceof TestSupport 来过滤* @param bean* @param beanName* @return* @throws BeansException*/@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
//        if (beanName.equals("testSupport")) {
//            log.info("执行  TestSupport 初始化前置方法");
//        }if (bean instanceof TestSupport) {log.info("bean 加工器捕捉到  TestSupport ,做初始化前置方法");}// do somethingreturn bean;}/*** bean 加工器之在bean实例化之后得预处理* @param bean* @param beanName* @return* @throws BeansException*/@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
//        if (beanName.equals("testSupport")) {
//            log.info("执行 TestSupport 初始化后置方法");
//        }if (bean instanceof TestSupport) {log.info("bean 加工器捕捉到  TestSupport ,做初始化后置方法");}// do somethingreturn bean;}
}
  • postProcessBeforeInitialization:bean 加工器之在bean初始化完毕之前的预处理
  • postProcessAfterInitialization:bean 加工器之在bean初始化之后的预处理
  • 这个扩展点是针对所有的bean的,所以如果需要观测特定的bean在BeanPostProcessor中的情况,需要通过 bean instanceof 或者 beanName equals 进行判断

log


2024-04-07 15:25:33.488  INFO 51628 --- [           main] com.ramble.beanlife.support.TestSupport  : TestSupport-BeanNameAware-setBeanName.param=testSupport
2024-04-07 15:25:35.271  INFO 51628 --- [           main] com.ramble.beanlife.support.TestSupport  : TestSupport-BeanFactoryAware-setBeanFactory.param=beanFactory
2024-04-07 15:25:35.783  INFO 51628 --- [           main] com.ramble.beanlife.support.TestSupport  : TestSupport-ApplicationContextAware-setApplicationContext.param="bean-life-app"
2024-04-07 15:25:36.198  INFO 51628 --- [           main] c.r.b.processor.BeanPostProcessorImpl    : bean 加工器捕捉到  TestSupport ,做初始化前置方法
2024-04-07 15:25:36.651  INFO 51628 --- [           main] com.ramble.beanlife.support.TestSupport  : 通过 @PostConstruct 注解执行自定义初始化逻辑
2024-04-07 15:25:36.652  INFO 51628 --- [           main] com.ramble.beanlife.support.TestSupport  : TestSupport-InitializingBean-afterPropertiesSet
2024-04-07 15:25:38.453  INFO 51628 --- [           main] c.r.b.processor.BeanPostProcessorImpl    : bean 加工器捕捉到  TestSupport ,做初始化后置方法

通过log打印的顺序可以观测到bean初始化的各个扩展口的执行顺序。

代码

https://gitee.com/naylor_personal/ramble-spring-boot/tree/master/bean-life

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】

目录😋 任务描述 相关知识 测试说明 我的通关代码: 测试结果: 任务描述 本关任务:编写一个程序利用栈判断左、右圆括号是否配对。 相关知识 为了完成本关任务,你需要掌握:栈对括号的处理。 栈对括号的处理 &…

让PPT不再“难搞”:智能工具如何改变办公体验

PPT的世界是一场属于设计感与逻辑力的双重较量。那些字体配色的小心思,排版设计的大考验,无不让人抓耳挠腮。然而,科技的加持让这一切正悄然改变。比如,随着 ai生成ppt 工具的兴起,许多复杂操作正被重新定义&#xff0…

OpenLayers基础教程——WebGLPoints设置不同图标样式的方法

1、前言 在OpenLayers中,WebGLPoints与VectorLayer设置不同图标样式的方法有所不同。本文就来介绍一下如何在WebGLPoints图层中根据要素类型设置不同的图标样式。 2、ol.layer.Vector的实现方法 ol.layer.Vector设置不同图标的样式很简单,直接上代码&…

浅谈Kubernetes(K8s)之RC控制器与RS控制器

1.RC控制器 1.1RC概述 Replication Controller 控制器会持续监控正在运行的Pod列表,并保证相应类型的Pod的数量与期望相符合,如果Pod数量过少,它会根据Pod模板创建新的副本,反之则会删除多余副本。通过RC可实现了应用服务的高可用…

es 3期 第14节-全文文本分词查询

#### 1.Elasticsearch是数据库,不是普通的Java应用程序,传统数据库需要的硬件资源同样需要,提升性能最有效的就是升级硬件。 #### 2.Elasticsearch是文档型数据库,不是关系型数据库,不具备严格的ACID事务特性&#xff…

如何保证消息队列的高可用?(RabbitMQ)

RabbitMQ 是基于主从(非分布式)做高可用性的,RabbitMQ 有三种模式:单机模式、普通集群模式、镜像集群模式 1、单机模式:一般没人生产用单机模式 2、普通集群模式: 普通集群模式用于提高系统的吞吐量&…

CAPL如何设置或修改CANoe TCP/IP协议栈的底层配置

在CANoe中创建网络节点作为以太网主机时,可以给其配置独立的TCP/IP Stack。 配置的协议栈有一些底层配置参数可以在界面上设置或修改,比如: MTU上图中MTU显示500只是图形界面显示错误,正确值是1500。 TCP延迟确认这些参数也可以通过CAPL动态配置,甚至CAPL还可以配置很多界…

Linux中vi和vim的区别详解

文章目录 Linux中vi和vim的区别详解一、引言二、vi和vim的起源与发展三、功能和特性1、语法高亮2、显示行号3、编辑模式4、可视化界面5、功能扩展6、插件支持 四、使用示例1、启动编辑器2、基本操作 五、总结 Linux中vi和vim的区别详解 一、引言 在Linux系统中,vi和…

如何将自己的PHP类库发布到composer仓库

将自己的 PHP 类库发布到 Composer 仓库,需要经过一系列的准备和操作步骤,以下是详细说明: 准备工作 创建类库项目:确保你的 PHP 类库项目具有清晰的目录结构,遵循 PSR-4 等 PHP 编码规范。通常,类文件应…

android——录制屏幕

录制屏幕 1、界面 2、核心代码 import android.app.NotificationChannel import android.app.NotificationManager import android.app.PendingIntent import android.app.Service import android.content.Context import android.content.Intent import android.graphics.Bi…

自学高考的挑战与应对:心理调适、学习方法改进与考试技巧提升

一、自学参加高考的成功条件 (一)报名条件 基本要求 自学参加高考,首先需严格遵守国家的法律法规,这是参与高考的基本前提。具备高中同等学力是核心要素之一,意味着考生需通过自学掌握高中阶段的知识体系与学习能力…

SQL语句错误号:Incorrect integer value: ‘‘ for column ‘poi_id‘ at

SQL语句错误号:Incorrect integer value: for column poi_id at通用解决方案 在MySQL 5.7中,如果你遇到 Incorrect integer value: for column poi_id at row 1 错误,这通常意味着你尝试将一个空字符串插入到需要整数值的字段中。以下是几…

【密码学】SM4算法

一、 SM4算法简介 SM4算法是中国国家密码管理局于2012发布的一种分组密码算法,其官方名称为SMS4(SMS4.0),相关标准为GM/T 0002-2012《SM4分组密码算法》。SM4算法的分组长度和密钥长度均为128比特,采用非平衡Feistel结构。采用32…

Qt Xlsx安装教程

Qt Xlsx安装教程 安装perl 如果没有安装perl,请参考perl Window安装教程 下载QtXlsxWriter源码 下载地址 ming32-make编译32 lib库 C:\Qt\Qt5.12.12\5.12.12\mingw73_32>d: D:\>cd D:\Code\QtXlsxWriter-master\QtXlsxWriter-master D:\Code\QtXlsxWrit…

1. 机器学习基本知识(3)——机器学习的主要挑战

1.5 机器学习的主要挑战 1.5.1 训练数据不足 对于复杂问题而言,数据比算法更重要但中小型数据集仍然很普遍,获得额外的训练数据并不总是一件轻而易举或物美价廉的事情,所以暂时不要抛弃算法。 1.5.2 训练数据不具有代表性 采样偏差&#…

通配符SSL证书申请

一、通配符SSL证书点击DV类型通配符SSL证书 二、点击立即生成证书,可以自己在线生成CSR提交,生成的时候私钥代码保存一下。 三、点击继续【建议选择DNS,DNS是指域名解析方式认证】 四、然后去域名注册商添加解析,解析如果可以设置…

个人ffmpeg笔记(一)

环境安装 QT环境安装 运行qt…run安装 下载地址:https://download.qt.io/archive/qt/ 下载地址:https://download.qt.io/archive/qt/5.12/5.12.10/ sudo apt install --reinstall libxcb-xinerama0 解决xcb问题 Ubuntu16.04打开Qt显示/home/user/.co…

JavaEE之多线程的风险以及如何避免

上文我们了解了单线程以及线程的一些基本常见方法,但是多线程在一些方面会存在安全问题,此文我们来为多线程的安全 保驾护航!! 详情请见下文 1. 多线程带来的风险——线程安全 1.1 观察线程不安全 /*** 使用两个线程&#xff0c…

LoViT: 用于手术阶段识别的长视频Transformer|文献速递-生成式模型与transformer在医学影像中的应用

Title 题目 LoViT: Long Video Transformer for surgical phase recognition LoViT: 用于手术阶段识别的长视频Transformer 01 文献速递介绍 快速发展的手术数据科学(SDS)领域旨在通过先进利用手术室(OR)内医疗设备采集的数据…

pika:适用于大数据量持久化的类redis组件|简介及安装(一)

文章目录 0. 引言1. pika简介2. pika安装3. pika设置开机自启4. pika主从搭建5. pika哨兵模式实现自动容灾总结 0. 引言 最近因为公司中用到pika组件,于是将研究过程和理解进行系统记录,以供后续参考。 1. pika简介 pika是360开发的一款国产类redis的…