八 Bean的生命周期

八、Bean的生命周期

8.1 什么是Bean的生命周期

Spring其实就一个管理Bean对象工厂。它负责对象的创建,对象的销毁等。

所谓的生命周期就是:对象从创建开始到最终销毁的整个过程

什么时候创建Bean对象?

创建Bean对象的前后会调用什么方法?

Bean对象什么时候销毁?

Bean对象的销毁前后调用什么方法?

8.2 为什么要知道Bean的生命周期

其实生命周期的本质是:在哪个时间节点上调用了哪个类的哪个方法。

我们需要充分的了解在这个生命线上,都有哪些特殊的时间节点。

只有我们知道了特殊的时间节点都在哪,到时我们才可以确定代码写到哪。

我们可能需要在某个特殊的时间点上执行一段特定的代码,这段代码就可以放到这个节点上。当生命线走到这里的时候,自然会被调用。

8.3 Bean的生命周期之5步

Bean生命周期的管理,可以参考Spring的源码:AbstractAutowireCapableBeanFactory类的doCreateBean()方法。

Bean生命周期可以粗略的划分为五大步:

  • 第一步:实例化Bean
  • 第二步:Bean属性赋值
  • 第三步:初始化Bean
  • 第四步:使用Bean
  • 第五步:销毁Bean

编写测试程序:

定义一个Bean

package com.study.spring6.bean;/*** @author sqnugy* @version 1.0* @className User* @since 1.0**/
public class User {private String name;public User() {System.out.println("1.实例化Bean");}public void setName(String name) {this.name = name;System.out.println("2.Bean属性赋值");}public void initBean(){System.out.println("3.初始化Bean");}public void destroyBean(){System.out.println("5.销毁Bean");}}
<?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/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!--init-method属性指定初始化方法。destroy-method属性指定销毁方法。--><bean id="userBean" class="com.study.spring6.bean.User" init-method="initBean" destroy-method="destroyBean"><property name="name" value="zhangsan"/></bean></beans>
package com.study.spring6.test;import com.study.spring6.bean.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @author sqnugy* @version 1.0* @className BeanLifecycleTest* @since 1.0**/
public class BeanLifecycleTest {@Testpublic void testLifecycle(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");User userBean = applicationContext.getBean("userBean", User.class);System.out.println("4.使用Bean");// 只有正常关闭spring容器才会执行销毁方法ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext;context.close();}
}

执行结果:

需要注意的:

  • 第一:只有正常关闭spring容器,bean的销毁方法才会被调用。
  • 第二:ClassPathXmlApplicationContext类才有close()方法。
  • 第三:配置文件中的init-method指定初始化方法。destroy-method指定销毁方法。

8.4 Bean生命周期之7步

在以上的5步中,第3步是初始化Bean,如果你还想在初始化前和初始化后添加代码,可以加入“Bean后处理器”。

编写一个类实现BeanPostProcessor类,并且重写before和after方法:

package com.study.spring6.bean;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;/*** @author sqnugy* @version 1.0* @className LogBeanPostProcessor* @since 1.0**/
public class LogBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("Bean后处理器的before方法执行,即将开始初始化");return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("Bean后处理器的after方法执行,已完成初始化");return bean;}
}

在spring.xml文件中配置“Bean后处理器”:

<!--配置Bean后处理器。这个后处理器将作用于当前配置文件中所有的bean。-->
<bean class="com.study.spring6.bean.LogBeanPostProcessor"/>

一定要注意:在spring.xml文件中配置的Bean后处理器将作用于当前配置文件中所有的Bean。

执行测试程序:

如果加上Bean后处理器的话,Bean的生命周期就是7步了:

8.5 Bean生命周期之10步

如果根据源码跟踪,可以划分更细粒度的步骤,10步:

上图中检查Bean是否实现了Aware的相关接口是什么意思?

Aware相关的接口包括:BeanNameAwareBeanClassLoaderAwareBeanFactoryAware

  • 当Bean实现了BeanNameAware,Spring会将Bean的名字传递给Bean。
  • 当Bean实现了BeanClassLoaderAware,Spring会将加载该Bean的类加载器传递给Bean。
  • 当Bean实现了BeanFactoryAware,Spring会将Bean工厂对象传递给Bean。

测试以上10步,可以让User类实现5个接口,并实现所有方法:

  • BeanNameAware
  • BeanClassLoaderAware
  • BeanFactoryAware
  • InitializingBean
  • DisposableBean

代码如下:

package com.study.spring6.bean;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.*;/*** @author sqnugy* @version 1.0* @className User* @since 1.0**/
public class User implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean {private String name;public User() {System.out.println("1.实例化Bean");}public void setName(String name) {this.name = name;System.out.println("2.Bean属性赋值");}public void initBean(){System.out.println("6.初始化Bean");}public void destroyBean(){System.out.println("10.销毁Bean");}@Overridepublic void setBeanClassLoader(ClassLoader classLoader) {System.out.println("3.类加载器:" + classLoader);}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println("3.Bean工厂:" + beanFactory);}@Overridepublic void setBeanName(String name) {System.out.println("3.bean名字:" + name);}@Overridepublic void destroy() throws Exception {System.out.println("9.DisposableBean destroy");}@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("5.afterPropertiesSet执行");}
}
package com.study.spring6.bean;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;/*** @author sqnugy* @version 1.0* @className LogBeanPostProcessor* @since 1.0**/
public class LogBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {System.out.println("4.Bean后处理器的before方法执行,即将开始初始化");return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println("7.Bean后处理器的after方法执行,已完成初始化");return bean;}
}

执行结果:

通过测试可以看出来:

  • InitializingBean的方法早于init-method的执行。
  • DisposableBean的方法早于destroy-method的执行。

8.6 Bean的作用域不同,管理方式不同

Spring 根据Bean的作用域来选择管理方式。

  • 对于singleton作用域的Bean,Spring 能够精确地知道该Bean何时被创建,何时初始化完成,以及何时被销毁;
  • 而对于 prototype 作用域的 Bean,Spring 只负责创建,当容器创建了 Bean 的实例后,Bean 的实例就交给客户端代码管理,Spring 容器将不再跟踪其生命周期。

我们把之前User类的spring.xml文件中的配置scope设置为prototype

<?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/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!--init-method属性指定初始化方法。destroy-method属性指定销毁方法。--><bean id="userBean" class="com.study.spring6.bean.User" init-method="initBean" destroy-method="destroyBean" scope="prototype"><property name="name" value="zhangsan"/></bean><!--配置Bean后处理器。这个后处理器将作用于当前配置文件中所有的bean。--><bean class="com.study.spring6.bean.LogBeanPostProcessor"/></beans>

执行测试程序:

通过测试一目了然。只执行了前8步,第9和10都没有执行。

8.7 自己new的对象如何让Spring管理

有些时候可能会遇到这样的需求,某个java对象是我们自己new的,然后我们希望这个对象被Spring容器管理,怎么实现?

package com.study.spring6.bean;/*** @author sqnugy* @version 1.0* @className User* @since 1.0**/
public class User {
}
package com.study.spring6.test;import com.study.spring6.bean.User;
import org.junit.Test;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;/*** @author sqnugy* @version 1.0* @className RegisterBeanTest* @since 1.0**/
public class RegisterBeanTest {@Testpublic void testBeanRegister(){// 自己new的对象User user = new User();System.out.println(user);// 创建 默认可列表BeanFactory 对象DefaultListableBeanFactory factory = new DefaultListableBeanFactory();// 注册Beanfactory.registerSingleton("userBean", user);// 从spring容器中获取beanUser userBean = factory.getBean("userBean", User.class);System.out.println(userBean);}
}

执行结果:

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【入门篇】桃园结义【算法赛】——多语言版

题目跳转 python import os import sys# 请在此输入您的代码 print(3)C #include <stdio.h> #include <stdlib.h>int main(int argc, char *argv[]) {printf("%d",3);return 0; }C #include <iostream> using namespace std; int main() {// …

速看!!!24下软考系统分析师综合知识真题回忆,考点已更新

2024下半年软考考试已经结束了&#xff0c;为大家整理了网友回忆版的系统分析师真题及答案&#xff0c;总共30道题左右。 下半年考试的宝子们可以对答案预估分数&#xff01;准备明年考的宝子可以提前把握考试知识点和出题方向&#xff0c;说不定会遇到相同考点的题目&#xff…

HarmonyOS NEXT:模块化项目 ——修改应用图标+启动页等

涉及官方文档 应用配置文件应用/组件级配置图标资源规范 涉及到app.json5配置文件和module.json5配置文件 1、 icon和label的校验。 IDE从5.0.3.800版本开始&#xff0c;不再对module.json5中的icon和label做强制校验&#xff0c;因此module.json5与app.json5只需要选择其一…

dolphinscheduler

dolphinscheduler 官网地址&#xff1a; https://dolphinscheduler.apache.org/zh-cn/docs/3.2.1/about/hardware 1. 概念&#xff1a;dolphinscheduler是一个功能强大的开源调度系统&#xff0c;专为管理和调度大规模数据处理任务设计。 2. 特点&#xff1a; 分布式架构、支持…

Transformer-BiLSTM、Transformer、CNN-BiLSTM、BiLSTM、CNN五模型多变量回归预测

Transformer-BiLSTM、Transformer、CNN-BiLSTM、BiLSTM、CNN五模型多变量回归预测 目录 Transformer-BiLSTM、Transformer、CNN-BiLSTM、BiLSTM、CNN五模型多变量回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 吐血售&#xff01;聚划算&#xff01;Transforme…

【C++】C++11特性(上)

✨✨欢迎大家来到Celia的博客✨✨ &#x1f389;&#x1f389;创作不易&#xff0c;请点赞关注&#xff0c;多多支持哦&#x1f389;&#x1f389; 所属专栏&#xff1a;C 个人主页&#xff1a;Celias blog~ 目录 一、列表初始化 二、std::initializer_list 三、右值引用和移…

Maven 构建项目

Maven 是一个项目管理和构建工具&#xff0c;主要用于 Java 项目。它简化了项目的构建、依赖管理、报告生成、发布等一系列工作。 构建自动化&#xff1a;Maven 提供了一套标准化的构建生命周期&#xff0c;包括编译、测试、打包、部署等步骤&#xff0c;通过简单的命令就可以执…

在jquery里,使用$.each()函数循环数组,对象,dom的用法

介绍 $.each() 能遍历一维数组&#xff0c;多维数组&#xff0c;JSON对象&#xff0c;dom2元素。在开发中可以很高效的处理各种数据结构。前提&#xff0c;需要导入jquery 使用 遍历JSON对象 var objDemo {name: linda,age:12, desc: a girl};$.each(objDemo,function(i,va…

UniApp 应用、页面与组件的生命周期详解

UniApp 应用、页面与组件的生命周期详解 在uni-app中包含了 应用生命周期、页面生命周期、和组件生命周期&#xff08; Vue.js的&#xff09;函数。 应用生命周期 应用生命周期仅可在App.vue中监听&#xff0c;在其它页面监听无效。 <script>export default {onLaunc…

进程的创建/终止/等待/替换

目录 一、进程创建 &#xff08;一&#xff09;fork函数的概念 &#xff08;二&#xff09;fork函数示例 二、进程终止 &#xff08;一&#xff09;退出码的概念 &#xff08;二&#xff09;退出码的含义 &#xff08;三&#xff09;相关函数和指令 三、进程等待 &…

【c++丨STL】list的使用

&#x1f31f;&#x1f31f;作者主页&#xff1a;ephemerals__ &#x1f31f;&#x1f31f;所属专栏&#xff1a;C、STL 目录 前言 list简介 一、list的默认成员函数 构造函数(constructor) 析构函数 赋值重载 二、list的迭代器接口 迭代器的功能分类 三、list的容量…

CANoe导入CAN DataBase(DBC文件)

Canoe是一款用于汽车网络仿真和开发的工具&#xff0c;它支持导入DBC文件&#xff08;CAN Database文件&#xff09;以定义和配置CAN网络中的消息、信号和节点。 将DBC文件拷贝至我们的工程目录的DBC文件夹内&#xff0c;随后在Simulation Setup中右击DataBase&#xff0c;进…

nacos配置管理

1、增加依赖 <!--配置管理的依赖 --> <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId><version>2.1.0.RELEASE</version> </dependency><de…

每日OJ题_牛客_奇数位丢弃_找规律/模拟_C++_Java

目录 牛客_奇数位丢弃_找规律/模拟 题目解析 C代码1模拟 C代码2找规律 Java代码找规律 牛客_奇数位丢弃_找规律/模拟 奇数位丢弃_牛客题霸_牛客网 描述&#xff1a; 对于一个由 0..n 的所有数按升序组成的序列&#xff0c;我们要进行一些筛选&#xff0c;每次我们丢弃去…

解决table下tr或td选中不生效的问题

目录 一、问题描述 1.首先我们来看一下代码结构 2.检查代码&#xff08;鼠标右键或按下F12&#xff09; 3.解决方案 一、问题描述 解决table下tr或td选中不生效&#xff0c;页面刷新无效果 1.首先我们来看一下代码结构 这里我们的结构是table标签下的tr&#xff0c;tr当…

学籍拍照助手,中小学新生学籍证件照电脑端拍照教程

新学期过半&#xff0c;许多中小学学籍管理员都忙碌起来&#xff0c;为孩子们准备学籍所需的证件照。传统的照相馆拍摄、向家长收集都存在一些弊端&#xff0c;下面就来介绍如何使用校园学籍拍照助手&#xff0c;更智能的完成学籍证件照的拍摄。 1. 准备工作在开始之前&#xf…

SE30 程序运行时间评估

日常执行报表的时候 可能会遇到报表反应时间太长 用户无法接受的情况&#xff0c;此时 作为IT同事 需要分析程序的运行时间&#xff0c;可以使用SAP标准事务码SE30. 1、选择运行时分析-测量-立即执行&#xff08;有些程序可能没有此按钮 需联系开发增加&#xff09; 2、以发…

T-Rex Label标注

这个是做大量数据集的时候用到的&#xff0c;但我觉得他比labelimg好用。 仙人指路✈trexlabel 基本标注 如果是从新开始的话就是 导入图片然后进行直接标注 如果是后期添加图片继续标注&#xff0c;选择你需要的数据集格式&#xff0c;导入即可。 如此&#xff0c;进去就…

部署zabbix遇到问题: cannot find a valid baseurl for repo:centos-sclo-rh/x86 64 怎么解决 ?

安装 Zabbix 前端包&#xff0c;提示cannot find a valid baseurl for repo&#xff1a;centos-sclo-rh/x86 64 安装zabbix前端包 # yum install zabbix-web-mysql-scl zabbix-apache-conf-scl 解决办法&#xff1a; 原因是&#xff1a;CentOS7的SCL源在2024年6月30日停止维护…

小程序+公众号统一账号unionid,实现pc+公众号+小程序统一身份

一、微信开放平台 注册开发者账号、绑定公众号、小程序 二、小程序端获取unionid 1获取code wx.login({success: res > {console.log("getCode", res.code)this.getOpenId(res.code)}}) 2通过code调用后台方法获取openid,unionid 小程序端 getOpenId: functi…