详解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,一经查实,立即删除!

相关文章

找到sql里面参数字段占位符的位置,方便对字段进行加密存储

CCJSqlParserUtil工具是强大&#xff0c;难用也是真的&#xff0c;得分析sql的各种各样的表达式。从中递归找出业务需要的。 public class SqlExpressionAnalyzer {public static void main(String[] args) {String sql "select id,user_name from sys_user t1,sys_offi…

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.如何去操作对象 修改属性…

Jenkins 定时触发策略

每天晚上 11 点执行一次&#xff0c;可以按照以下步骤进行。 复制代码 import jenkins import datetime import base64USERNAME bUFNXssaaX0NU\n PASSWORD bUFNXXssdds0Ndclass JenkinsMonitor:def __init__(self, jobs_to_monitor):self.jenkins_url "http://pe-dddd…

fastJSON工具类

1 总结 1&#xff1a; JSONObject&#xff1a; 理解为 Map 2&#xff1a;JSONArray &#xff1a; 理解为List<Map> 3&#xff1a;JSON.toJSONString()&#xff1b;会将时间转为时间戳 4&#xff1a;toJSONStringWithDateFormat 同一个字符串中 时间格式是统一格式 2 转成…

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

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

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

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

AND 运算符的优先级高于 OR

在 SQL 中&#xff0c;AND 运算符的优先级高于 OR。这意味着您的查询可能会不按预期执行。为了确保逻辑的正确性&#xff0c;您可能需要使用括号来明确指定运算符的优先级。 正确的&#xff1a;and后用括号把or括起来 SELECT * FROM student WHERE data_status 0 AND (name L…

python-docx 实现 Word 办公自动化

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

图像直方图比较

对于直方图的比较&#xff0c;我们可以使用 OpenCV 提供的函数 compareHist() 进行比较&#xff0c;从而得到一个数值&#xff0c;表示两个直方图的匹配程度&#xff08;相似性&#xff09;。 原理 对于两个直方图&#xff08; H 1 H_{1} H1​ 和 H 2 H_{2} H2​&#xff09…

【大数据】基础认知入门

目录 前言阅读对象阅读导航前置知识笔记正文一、什么是大数据1.1 定义1.2 特点1.3 数据结构1.4 补充总结 二、大数据能用来干什么2.1 应用方向2.2 应用场景&#xff08;简述&#xff09;2.3 总结 三、大数据一般性过程四、给自己的作业 感谢说在后面 前言 唉&#xff0c;最近有…

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…

【Android高级UI】将View或Layout裁剪为任意形状

需求 将View裁剪为指定形状 将Layout裁剪为指定形状&#xff0c;并且Children不能超过裁剪范围 应用 圆角图片异形图片圆角Layout 方案 通过ViewOutlineProvider裁剪控件范围 实现 fun View.getMeasureSize(): Size {val widthSpec View.MeasureSpec.makeMeasureSpec(…

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

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

Hadoop入门基础(三):Hadoop启动踩坑记录

一、机器ssh连接方式非默认22端口 报错&#xff1a; sbin/start-dfs.sh Starting namenodes on [doop253] doop253: ssh: connect to host doop253 port 22: Connection refused 解决方法&#xff1a; sudo vim /etc/ssh/ssh_config 添加如下内容&#xff08;注意替换自己服…

[Qt] 避免CMake编译的Qt程序单独运行时出现控制台窗口的解决办法

只需要在add_executable中加上WIN32即可 避免CMake编译的Qt程序单独运行时出现控制台窗口的解决办法

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

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

【Harmony OS 4.0】交互事件(手势事件)

1. 绑定手势方法 1.1 gesture&#xff08;常规手势绑定方法&#xff09; 1.2 priorityGesture&#xff08;带优先级的手势绑定方法&#xff09; 1.3 parallelGesture&#xff08;并行手势绑定方法&#xff09; 可以在父子组件上绑定。可以同时响应的相同手势。当父组件绑定了…

如何清理win备用内存?备用内存过大怎么办?

下载这个软件RamMap 运行以后 选择Empty-Empty Standby List就行了 参考&#xff1a;https://www.zhihu.com/question/263768043 另外&#xff0c;禁用服务中的SystemMain&#xff0c;应该会停止占用备用内存&#xff0c;但是需要重启。 所以没办法只好创建一个任务计划&…