【Spring高级】第3讲 Bean的生命周期
目录
- 基本的生命周期
- 后处理器
- 总结
基本的生命周期
为了演示生命周期的过程,我们直接使用 SpringApplication.run()方法,他会直接诶返回一个容器对象。
import org.springframework.boot.SpringApplication;
import org.springframework.context.ConfigurableApplicationContext;@SpringBootApplication
public class BeanLifecycleTest {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(BeanLifecycleTest.class, args);context.close();}
}
然后定义一个Bean,如下:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;@Component
public class LifeCycleBean {public LifeCycleBean() {System.out.println("构造方法");}/*** 依赖注入方法* 当参数是一个对象时,可以直接注入* 但是如果是String类型,则需要使用@Value,找到环境变量JAVA_HOME** @param home*/@Autowiredpublic void autowired(@Value("${JAVA_HOME}") String home) {System.out.println("依赖注入");}/*** @PostConstruct 用来标记 bean 初始化完成后的回调方法*/@PostConstructpublic void init() {System.out.println("初始化");}/*** @PreDestroy 用来标记 bean 销毁前的回调方法*/@PreDestroypublic void destory() {System.out.println("销毁");}}
上面的LifeCycleBean我们定义了构造方法、初始化方法、依赖注入方法、销毁方法。
启动应用,打印如下:
构造方法
依赖注入
初始化
2024-02-29 22:53:29.169 INFO 39870 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2024-02-29 22:53:29.182 INFO 39870 --- [ main] c.c.demo02.chapter03.BeanLifecycleTest : Started BeanLifecycleTest in 1.724 seconds (JVM running for 7.593)
2024-02-29 22:53:29.191 INFO 39870 --- [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
销毁
上面就可以看出整个流程。
后处理器
除了基本的生命周期,下面看下加上后处理器后的流程。
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.stereotype.Component;@Component
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {@Overridepublic void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {if (beanName.equals("lifeCycleBean")) {System.out.println("<<<<< postProcessBeforeDestruction 销毁之前执行");}}@Overridepublic Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {if (beanName.equals("lifeCycleBean")) {System.out.println("<<<<< postProcessBeforeInstantiation 实例化之前执行");}return null;
// return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInstantiation(beanClass, beanName);}@Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {if (beanName.equals("lifeCycleBean")) {System.out.println("<<<<< postProcessBeforeInstantiation 实例化之后执行");}// 如果返回false会跳过依赖注入阶段return true;
// return InstantiationAwareBeanPostProcessor.super.postProcessAfterInstantiation(bean, beanName);}@Overridepublic PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {// 依赖注入阶段执行,如@Autowired,@Value @Resourceif (beanName.equals("lifeCycleBean")) {System.out.println("<<<<< postProcessProperties 依赖注入阶段执行");}return null;
// return InstantiationAwareBeanPostProcessor.super.postProcessProperties(pvs, bean, beanName);}@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {// 初始化之前执行,如@PostConstruct,@ConfigurationPropertiesif (beanName.equals("lifeCycleBean")) {System.out.println("<<<<< postProcessBeforeInitialization 初始化之前执行");}return null;
// return InstantiationAwareBeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {// 一般这个阶段是替换掉原有的bean,代替增强if (beanName.equals("lifeCycleBean")) {System.out.println("<<<<< postProcessAfterInitialization 初始化之后执行");}return null;
// return InstantiationAwareBeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);}
}
再次执行,结果如下
<<<<< postProcessBeforeInstantiation 实例化之前执行
构造方法
<<<<< postProcessBeforeInstantiation 实例化之后执行
<<<<< postProcessProperties 依赖注入阶段执行
依赖注入
<<<<< postProcessBeforeInitialization 初始化之前执行
<<<<< postProcessAfterInitialization 初始化之后执行
2024-02-29 23:47:57.110 INFO 42057 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2024-02-29 23:47:57.145 INFO 42057 --- [ main] c.c.demo02.chapter03.BeanLifecycleTest : Started BeanLifecycleTest in 2.242 seconds (JVM running for 8.116)
2024-02-29 23:47:57.158 INFO 42057 --- [ main] o.apache.catalina.core.StandardService : Stopping service [Tomcat]
<<<<< postProcessBeforeDestruction 销毁之前执行
销毁
通过上面可以看出,各个后置处理器分别作用在Bean生命周期的哪个阶段了。
总结
基本生命周期
创建前后的增强
postProcessBeforeInstantiation:这里返回的对象若不为 null 会替换掉原本的 bean,并且仅会走 postProcessAfterInitialization 流程postProcessAfterInstantiation:这里如果返回 false 会跳过依赖注入阶段
依赖注入前的增强
postProcessProperties:如 @Autowired、@Value、@Resource
初始化前后的增强
postProcessBeforeInitialization:这里返回的对象会替换掉原本的 bean,如 @PostConstruct、@ConfigurationPropertiespostProcessAfterInitialization:这里返回的对象会替换掉原本的 bean,如代理增强
销毁之前的增强
postProcessBeforeDestruction:如 @PreDestroy
相关文章:
【Spring高级】第3讲 Bean的生命周期
目录 基本的生命周期后处理器总结 基本的生命周期 为了演示生命周期的过程,我们直接使用 SpringApplication.run()方法,他会直接诶返回一个容器对象。 import org.springframework.boot.SpringApplication; import org.springframework.context.Config…...
【C语言】linux内核tcp_write_xmit和tcp_write_queue_purge
tcp_write_xmit 一、讲解 这个函数 tcp_write_xmit 是Linux内核TCP协议栈中的一部分,其基本作用是发送数据包到网络。这个函数会根据不同情况推进发送队列的头部,确保只要远程窗口有空间,就可以发送数据。 下面是对该函数的一些主要逻辑的中…...
opencv实现视频人脸识别
一. 实现指定图像的人脸识别 注意: 以下实例参考《OpenCV轻松入门面向Python》李立宗著,使用python语言,编辑器为PyCharm,且都运行成功。 1.dface3.jpg图片文件和当前代码放在同一级目录下。 2.级联分类器文件和当前代码文件放在…...
【今日面经】24/3/9 广州Java某小厂电话面经
面经来源:https://www.nowcoder.com/?type818_1 目录 1、 和equals()有什么区别?2、String变量直接赋值和构造函数赋值比较相等吗?3、String一些方法?4、抽象类和接口有什么区别?5、Java容器有哪些?6、Lis…...
日期问题---算法精讲
前言 今天讲讲日期问题,所谓日期问题,在蓝桥杯中出现众多,但是解法比较固定。 一般有判断日期合法性,判断是否闰年,判断日期的特殊形式(回文或abababab型等) 目录 例题 题2 题三 总结 …...
倒计时35天
dp预备(来源:b站acm刘春英老师) 1. 2. 3. 4. 5. 6. 7....
JAVA后端开发面试基础知识(七)——多线程
1. 线程池原理 优点 降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线…...
Apache的安装与目录结构详细解说
1. Apache安装步骤 Apache是一款开源的Web服务器软件,常用于搭建网站和服务。以下是Apache的安装步骤: 在官方网站(https://httpd.apache.org/)下载最新版本的Apache软件包。解压下载的软件包到指定目录。运行安装程序ÿ…...
axios的详细使用
目录 axios:现代前端开发的HTTP客户端王者 一、axios简介 二、axios的基本用法 1. 安装axios 2. 发起GET请求 3. 发起POST请求 三、axios的高级特性 1. 拦截器 2. 取消请求 3. 自动转换JSON数据 四、axios在前端开发中的应用 五、总结 axios:…...
空间复杂度的OJ练习——轮转数组
旋转数组OJ链接:https://leetcode-cn.com/problems/rotate-array/ 题目: 思路: 通过题目我们可以知道这是一个无序数组,只需要将数组中的数按给定条件重新排列,因此我们可以想到以下几种方法: 1.暴力求解法…...
学习与学习理论 - 2024教招 - test
一 方向 所有学习理论大的观点,到某个人物个人的观点。抖音:按照粉丝数量、收藏数量、点赞数量排名从编程(思想)、java、自己所拥有的特点看学习方法顺序:java、自身、教学理论的总观点、教学理论代表人物的观点、散兵…...
Spring web开发(入门)
1、我们在执行程序时,运行的需要是这个界面 2、简单的web接口(127.0.0.1表示本机IP) package com.example.demo;import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestCont…...
这是谁的女儿?其母亲早已红过头了,现在小小年纪的她也爆红网络,没想到吧?
这是谁的女儿?其母亲早已红过头了,现在小小年纪的她也爆红网络,没想到吧? 原来,作母亲的她在红极一时后似乎沉寂了下来,没想到她11岁的女儿近年来也在社交媒体上走红,她为何也成了小网红呢&…...
鸿蒙开发之gson解析
作为老牌的Java程序员,几乎每个项目都逃不掉fastjson/gson等三方库。那么在OpenHarmony/HarmonyOS应用开发中,做数据解析时能不能使用fastjson/gson三方库呢?于是我搜索了一下,其实在arkts开发过程中也是可以使用JS里自带的JSONparse和JSONstringify方法来实现JSON和对象转…...
图形库实战丨C语言扫雷小游戏(超2w字,附图片素材)
目录 效果展示 游玩链接(无需安装图形库及VS) 开发环境及准备 1.VS2022版本 2.图形库 游戏初始化 1.头文件 2.创建窗口 3.主函数框架 开始界面函数 1.初始化 1-1.设置背景颜色及字体 1-2.处理背景音乐及图片素材 1-3.处理背景图位置 2.选…...
c++: string中 find, rfind, find_frist_of, find_laste_of 与 substr之间的操作
在 C 的 std::string 类中,有几个成员函数可以用于在字符串中执行搜索和子字符串提取操作。以下是这些函数的简要说明: find(): 查找子字符串的第一个出现位置。 size_t find(const string& str, size_t pos 0) const; size_t find(const char* s, …...
[python3] dataclass的对象排序
在使用 dataclass(orderTrue) 中,会比较数据类中定义的所有属性。具体来说,生成的比较运算符方法会按照数据类中定义属性的顺序逐个比较属性的取值。 下面是一个示例代码,演示了 orderTrue 比较数据类中所有属性的情况: from da…...
数据库基础——mysql知识体系(掌握mysql,看完这篇文章就够了)
1.关系型数据库 关系型数据库是一种基于关系模型的数据库系统,将数据组织成表格的形式,表格由行和列组成,每行代表一个记录,每列代表一个属性。它使用结构化查询语言SQL进行数据管理和操作。 特点:1.数据的组织&…...
Zynq—AD9238数据采集DDR3缓存千兆以太网发送实验(二)
Zynq—AD9238数据采集DDR3缓存千兆以太网发送实验(前导) Zynq—AD9238数据采集DDR3缓存千兆以太网发送实验(一) Zynq—AD9238数据采集DDR3缓存千兆以太网发送实验(三) 五、实验目的 本次实验使用电脑上的…...
高级语言讲义2010计专(仅高级语言部分)
1.编写一程序,对输入的正整数,求他的约数和。 如:18的约数和为1236939 #include <stdio.h>int getsum(int n){int i,sum0;for(i1;i<n;i)if(n%i0)sumi;return sum; } int main(){int sum getsum(18);printf("%d",sum); …...
CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...
逻辑回归暴力训练预测金融欺诈
简述 「使用逻辑回归暴力预测金融欺诈,并不断增加特征维度持续测试」的做法,体现了一种逐步建模与迭代验证的实验思路,在金融欺诈检测中非常有价值,本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...
Mac flutter环境搭建
一、下载flutter sdk 制作 Android 应用 | Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 1、查看mac电脑处理器选择sdk 2、解压 unzip ~/Downloads/flutter_macos_arm64_3.32.2-stable.zip \ -d ~/development/ 3、添加环境变量 命令行打开配置环境变量文件 ope…...
