详解Spring Bean的生命周期

详解Bean的生命周期

前言

在我们没有使用Spring框架之前,创建对象一般都是使用new关键字进行创建,当然除了new关键字外,还有

  • 运用反射手段,使用Class类的newInstance方法 或者 Constructor类中的newInstance方法
  • 使用clone方法
  • 使用反序列化(ObjectInputStream)

一旦对象不再被使用的时候,将有可能被JVM垃圾回收器进行回收。

但是在Spring通过IOC容器进行管理之后,Bean 的生命周期就变得更加复杂了,下图展示了Bean的构造过程

在这里插入图片描述

Bean的生命周期

我们对上图的每个步骤进行文字说明

  • Spring启动,查找并加载需要被Spring管理的bean,进行Bean的实例化
  • Bean实例化后对将Bean的引入和值注入到Bean的属性中
  • 如果Bean实现了BeanNameAware接口的话,Spring将Bean的Id传递给setBeanName()方法
  • 如果Bean实现了BeanFactoryAware接口的话,Spring将调用setBeanFactory()方法,将BeanFactory容器实例传入
  • 如果Bean实现了ApplicationContextAware接口的话,Spring将调用Bean的setApplicationContext()方法,将bean所在应用上下文引用传入进来。
  • 如果Bean实现了BeanPostProcessor接口,Spring就将调用他们的postProcessBeforeInitialization()方法。
  • 如果Bean 实现了InitializingBean接口,Spring将调用他们的afterPropertiesSet()方法。类似的,如果bean使用init-method声明了初始化方法,该方法也会被调用
  • 如果Bean 实现了BeanPostProcessor接口,Spring就将调用他们的postProcessAfterInitialization()方法。
  • 此时,Bean已经准备就绪,可以被应用程序使用了。他们将一直驻留在应用上下文中,直到应用上下文被销毁。
  • 如果bean实现了DisposableBean接口,Spring将调用它的destory()接口方法,同样,如果bean使用了destory-method 声明销毁方法,该方法也会被调用。

接口方法的分类

Bean的完整生命周期经历了各种方法的调用,这些方法可以分类一下三类

Bean自身的方法:

这个包括了Bean本身调用的方法和通过配置文件中的init-method和destroy-method指定的方法

Bean级生命周期的方法

这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法

容器级生命周期的方法

这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。

工程后处理器接口方法

这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器  接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。

DEMO举例

我们用一个简单的Spring Bean来演示一下Spring Bean的生命周期。

首先是一个简单的Spring Bean,调用Bean自身的方法和Bean级生命周期接口方法,为了方便演示,它实现了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这4个接口,同时有2个方法,对应配置文件中的init-method和destroy-method。如下:

package springBeanTest;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.DisposableBean;
import org.springframework.beans.factory.InitializingBean;public class Person implements BeanFactoryAware, BeanNameAware,InitializingBean, DisposableBean {private String name;private String address;private int phone;private BeanFactory beanFactory;private String beanName;public Person() {System.out.println("【构造器】调用Person的构造器实例化");}public String getName() {return name;}public void setName(String name) {System.out.println("【注入属性】注入属性name");this.name = name;}public String getAddress() {return address;}public void setAddress(String address) {System.out.println("【注入属性】注入属性address");this.address = address;}public int getPhone() {return phone;}public void setPhone(int phone) {System.out.println("【注入属性】注入属性phone");this.phone = phone;}@Overridepublic String toString() {return "Person [address=" + address + ", name=" + name + ", phone="+ phone + "]";}// 这是BeanFactoryAware接口方法@Overridepublic void setBeanFactory(BeanFactory arg0) throws BeansException {System.out.println("【BeanFactoryAware接口】调用BeanFactoryAware.setBeanFactory()");this.beanFactory = arg0;}// 这是BeanNameAware接口方法@Overridepublic void setBeanName(String arg0) {System.out.println("【BeanNameAware接口】调用BeanNameAware.setBeanName()");this.beanName = arg0;}// 这是InitializingBean接口方法@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("【InitializingBean接口】调用InitializingBean.afterPropertiesSet()");}// 这是DiposibleBean接口方法@Overridepublic void destroy() throws Exception {System.out.println("【DiposibleBean接口】调用DiposibleBean.destory()");}// 通过<bean>的init-method属性指定的初始化方法public void myInit() {System.out.println("【init-method】调用<bean>的init-method属性指定的初始化方法");}// 通过<bean>的destroy-method属性指定的初始化方法public void myDestory() {System.out.println("【destroy-method】调用<bean>的destroy-method属性指定的初始化方法");}
}

接下来是演示BeanPostProcessor接口的方法,如下:

package springBeanTest;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;public class MyBeanPostProcessor implements BeanPostProcessor {public MyBeanPostProcessor() {super();System.out.println("这是BeanPostProcessor实现类构造器!!");// TODO Auto-generated constructor stub}@Overridepublic Object postProcessAfterInitialization(Object arg0, String arg1)throws BeansException {System.out.println("BeanPostProcessor接口方法postProcessAfterInitialization对属性进行更改!");return arg0;}@Overridepublic Object postProcessBeforeInitialization(Object arg0, String arg1)throws BeansException {System.out.println("BeanPostProcessor接口方法postProcessBeforeInitialization对属性进行更改!");return arg0;}
}

如上,BeanPostProcessor接口包括2个方法postProcessAfterInitialization和postProcessBeforeInitialization,这两个方法的第一个参数都是要处理的Bean对象,第二个参数都是Bean的name。返回值也都是要处理的Bean对象。这里要注意。

InstantiationAwareBeanPostProcessor 接口本质是BeanPostProcessor的子接口,一般我们继承Spring为其提供的适配器类InstantiationAwareBeanPostProcessor Adapter来使用它,如下:

package springBeanTest;import java.beans.PropertyDescriptor;import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;public class MyInstantiationAwareBeanPostProcessor extendsInstantiationAwareBeanPostProcessorAdapter {public MyInstantiationAwareBeanPostProcessor() {super();System.out.println("这是InstantiationAwareBeanPostProcessorAdapter实现类构造器!!");}// 接口方法、实例化Bean之前调用@Overridepublic Object postProcessBeforeInstantiation(Class beanClass,String beanName) throws BeansException {System.out.println("InstantiationAwareBeanPostProcessor调用postProcessBeforeInstantiation方法");return null;}// 接口方法、实例化Bean之后调用@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName)throws BeansException {System.out.println("InstantiationAwareBeanPostProcessor调用postProcessAfterInitialization方法");return bean;}// 接口方法、设置某个属性时调用@Overridepublic PropertyValues postProcessPropertyValues(PropertyValues pvs,PropertyDescriptor[] pds, Object bean, String beanName)throws BeansException {System.out.println("InstantiationAwareBeanPostProcessor调用postProcessPropertyValues方法");return pvs;}
}

参考

https://www.cnblogs.com/zrtqsk/p/3735273.html

https://www.cnblogs.com/javazhiyin/p/10905294.html

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

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

相关文章

JavaScript语法基础之DOM基础

目录 1. DOM 基础 1.1. DOM 是什么&#xff1f; 1.1.1. DOM 对象 1.1.2. DOM 结构 1.2. 节点类型 1.3. 获取元素 1.3.1. getElementById() 1.3.2. getElementsByTagName() 1.3.3. getElementsByClassName() 1.3.4. getElementsByName() 1.4.如何去操作对象 修改属性…

IP SSL证书的未来趋势:适应不断变化的安全挑战

随着网络攻击手段的不断进化和用户对隐私保护意识的增强&#xff0c;IP SSL证书作为保障网络安全的关键组件之一&#xff0c;也在不断地发展和完善。本文将探讨IP SSL证书的未来趋势&#xff0c;以及如何适应这些不断变化的安全挑战。 当前状况与挑战 网络安全意识提升&#…

ARM 裸机与 Linux 驱动对比及 Linux 内核入门

目录 ARM裸机代码和驱动的区别 Linux系统组成 内核五大功能 设备驱动分类 内核类型 驱动模块 驱动模块示例 Makefile配置 命令 编码辅助工具 内核中的打印函数 printk 函数 修改打印级别 ​编辑 打印级别含义 驱动多文件编译 示例 模块传递参数 命令行传递参数…

python-docx 实现 Word 办公自动化

前言&#xff1a;当我们需要批量生成一些合同文件或者简历等。如果手工处理对于我们来说不仅工作量巨大&#xff0c;而且难免会出现一些问题。这个时候运用python处理word实现自动生成文件可极大的提高工作效率。 python-docx是python的第三方插件&#xff0c;用来处理word文件…

Kubectl命令、初识pod、namespace

文章目录 一、Kubectl简介基础命令1.基本信息命令2.创建和更新资源命令3.删除资源命令4. 查看日志和调试命令5. 端口转发和复制文件命令6. 部署管理命令7. 伸缩命令8. 配置和上下文管理命令9.常用命令 二、Pod简介核心概念pod常见状态调度和初始化阶段容器创建和运行阶段异常状…

Qt网络通信——TCP和UDP

一、TCP通信 TCP通信必须先建立 TCP 连接&#xff0c;通信端分为客户端和服务器端。 Qt 为服务器端提供了 QTcpServer 类用于实现端口监听&#xff0c;QTcpSocket 类则用于服务器和客户端之间建立连接。大致流程如下图所示&#xff1a; 1. 服务器端建立 1.1 监听——listen() …

PPP简介

介绍PPP特性的定义和目的。 定义 PPP&#xff08;Point-to-Point Protocol&#xff09;协议是一种点到点链路层协议&#xff0c;主要用于在全双工的同异步链路上进行点到点的数据传输。 目的 PPP协议是在串行线IP协议SLIP&#xff08;Serial Line Internet Protocol&#x…

代码随想录:动态规划6-10

62、不同路径 题目 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少条不同的路径…

史上最全的软件工厂考试简答题教程

软件工程考试简答题 1. 有人认为软件开发时&#xff0c;一个错误发现得越晚&#xff0c;为改正它所付出的代价越大。提出你的观点并解释原因&#xff1f; &#xff08;1&#xff09;在软件开发的不同阶段进行修改付出的代价是很不相同的&#xff0c;在早期引入变动&#xff0c…

openai whisper使用

whisper使用 介绍 Whisper是一种通用的语音识别模型。它是在大量不同音频数据集上训练的&#xff0c;也是一个多任务模型&#xff0c;可以执行多语言语音识别、语音翻译和语言识别。 GitHub&#xff1a;https://github.com/openai/whisper 论文链接&#xff1a;https://arx…

注册Github账号详细过程

目录 一、准备工作 二、注册步骤 一、准备工作 在注册GitHub账号之前&#xff0c;请确保您已经准备好以下信息&#xff1a; 一个有效的电子邮箱地址&#xff1a;用于接收验证邮件和GitHub的后续通知。 用户名&#xff1a;确保该用户名在GitHub上是唯一的&#xff0c;且符合…

turtle画图知识

Turtle库是Python编程语言中的一个库&#xff0c;用于创建各种类型的图形&#xff0c;包括简单圆形、线条、路径和图片。它支持多种图形类型&#xff0c;并且可以绘制出各种复杂的形状。 以下是一些基本的使用方法&#xff1a; 1. 创建一个新的Turtle对象&#xff1a; pytho…

Leetcode JAVA刷刷站(53)最大子数组和

一、题目概述 二、思路方向 这个问题是一个经典的算法问题&#xff0c;称为“最大子序和”&#xff08;Maximum Subarray Problem&#xff09;。解决这个问题的一个高效方法是使用“Kadanes Algorithm”&#xff0c;它只需要遍历数组一次&#xff0c;就能在 O(n) 时间复杂度内…

CVPR2023《DNF: Decouple and Feedback Network for Seeing in the Dark》暗光图像增强论文阅读笔记

相关链接 论文链接 https://openaccess.thecvf.com/content/CVPR2023/papers/Jin_DNF_Decouple_and_Feedback_Network_for_Seeing_in_the_Dark_CVPR_2023_paper.pdf 代码链接 https://github.com/Srameo/DNF 摘要 RAW数据的独特属性在低光照图像增强方面展现出巨大潜力。…

C语言典型例题47

《C程序设计教程&#xff08;第四版&#xff09;——谭浩强》 习题3.7 输入4个整数&#xff0c;要求按照从小到大的顺序输出 4个数之间进行比较&#xff0c;冒泡排序最最最详细过程&#xff0c;如果想更改为任意数之间相互比较&#xff0c;只需要修改两个地方&#xff08;数组大…

力扣面试经典算法150题:买卖股票的最佳时机 II

买卖股票的最佳时机 II 今天的题目是力扣面试经典150题中的数组的中等难度题&#xff1a;买卖股票的最佳时机 II。 题目链接&#xff1a;https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/description/?envTypestudy-plan-v2&envIdtop-interview-150 问…

教程:postman的平替hoppscotch,又叫postwoman,hoppscotch的docker-compose安装过程

目录 1. 背景2. 前期准备2.1 准备docker-compose文件&#xff0c;两个版本&#xff0c;一个3合1&#xff0c;一个分开2.1.1 3合1版本&#xff08;推荐&#xff09;2.1.2 独立版本 2.2 准备安装nginx-proxy-manager&#xff08;可选&#xff09;2.2 准备.env文件2.2.1 默认ip的.…

Spring Boot OAuth2.0应用

本文展示Spring Boot中&#xff0c;新版本OAuth2.0的简单实现&#xff0c;版本信息&#xff1a; spring-boot 2.7.10 spring-security-oauth2-authorization-server 0.4.0 spring-security-oauth2-client 5.7.7 spring-boot-starter-oauth2-resource-server 2.7.10展示三个服务…

Android高版本抓包总结

方案1 CharlesVirtualXposedJustTrustMe 推荐使用三星手机此方案 VirtualXposed下载链接&#xff1a;https://github.com/android-hacker/VirtualXposed/releases JustTrustMe下载链接&#xff1a;https://github.com/Fuzion24/JustTrustMe/releases/ 下载完成后使用adb命令…

从易车“超级818冠军之夜” 看如何借势体育营销点燃汽车消费热潮

编辑 | 魏力 发布 | 大力财经 导语&#xff1a;这个8月&#xff0c;是属于奥运的8月。 巴黎奥运会虽圆满落幕&#xff0c;但属于奥运健儿们的热度还在持续。在这股奥运热潮的带动下&#xff0c;全民运动热情持续释放&#xff0c;同时也激发出巨大的消费潜力。 赛场外&#…