05-Spring中Bean的生命周期

Bean的生命周期

生命周期就是对象从创建开始到最终销毁的整个过程 , Spring其实就是一个管理Bean对象的工厂,它负责对象的创建和销毁等

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

  • 研究生命周期的意义:在哪个时间节点上调用了哪个类的哪个方法,把需要在某个特殊的时间点上执行的一段代码放到对应节点上,然后到点会自动被调用

Bean的生命周期之五步

第一步:实例化Bean(调用无参数构造方法)

第二步:给Bean属性赋值(调用set方法)

第三步:初始化Bean(会调用Bean的init方法, 这个init方法需要自己写,并且在配置文件中需要使用init-method属性指定)

第四步:使用Bean

第五步:销毁Bean(会调用Bean的destroy方法, 这个destroy方法需要自己写,并且在配置文件中需要使用destroy-method属性指定)

  • 只有手动关闭Spring容器, bean的销毁方法才会被调用,需要向下转型执行ClassPathXmlApplicationContext特有的close方法
    在这里插入图片描述

定义一个Bean

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属性赋值");}//配置bean的初始化方法public void initBean(){System.out.println("3.初始化Bean");}//配置bean的销毁方法public void destroyBean(){System.out.println("5.销毁Bean");}
}

编写spring的配置文件: init-method属性指定初始化方法名, destroy-method属性指定销毁方法名

<?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"><!--手动指定Bean的初始化方法和销毁方法--><bean id="userBean" class="com.powernode.spring6.bean.User" init-method="initBean" destroy-method="destroyBean"><property name="name" value="zhangsan"/></bean>
</beans>

测试结果的执行顺序: 1.实例化Bean-->2.Bean属性赋值-->3.初始化Bean-->4.使用Bean-->5.销毁Bean

public class BeanLifecycleTest {@Testpublic void testLifecycle(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");//以下这行代码执行了1.实例化Bean-->2.Bean属性赋值-->3.初始化BeanUser userBean = applicationContext.getBean("userBean", User.class);System.out.println("4.使用Bean");// 必须手动关闭Spring容器才会销毁Bean从而执行Bean的销毁方法ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext;context.close();}
}

Bean生命周期之七步(掌握)

如果你还想在besn的初始化前和初始化后添加代码,需要加入Bean后处理器(编写一个类实现BeanPostProcessor接口并且实现before和after方法)

  • Bean后处理器将作用于整个配置文件中所有的bean

在这里插入图片描述

编写日志的Bean后处理器实现BeanPostProcessor接口并实现postProcessBeforeInitialization和postProcessAfterInitialization方法

  • 这两个方法都有两个参数:第一个参数是刚创建的bean对象, 第二个参数是bean的名字
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的配置文件中配置Bean后处理器(作用于当前配置文件中所有的Bean),并手动指定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">    <!--这个Bean后处理器将作用于整个配置文件中所有的bean--><bean class="com.powernode.spring6.bean.LogBeanPostProcessor"/><!--普通bean--><bean id="userBean" class="com.powernode.spring6.bean.User" init-method="initBean" destroy-method="destroyBean"><property name="name" value="zhangsan"/></bean>
</beans>

测试结果: 1.实例化Bean–>2.Bean属性赋值–>Bean后处理器的before方法–>3.初始化Bean–>Bean后处理器的after方法–>4.使用Bean–>5.销毁Bean

public class BeanLifecycleTest {@Testpublic void testLifecycle(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");// 以下这行代码执行了1.实例化Bean-->2.Bean属性赋值-->Bean后处理器的before方法-->3.初始化Bean-->Bean后处理器的after方法User userBean = applicationContext.getBean("userBean", User.class);System.out.println("4.使用Bean");// 必须手动关闭Spring容器才会销毁Bean从而执行Bean的销毁方法ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext;context.close();}
}

Bean生命周期之十步(了解)

多添加了三个点位用来检查你这个Bean是否实现了某些特定的接口,如果实现了这些接口则Spring容器会调用这些接口中的方法

  • 调用这些接口中的方法目的是为了给你传递一些数据,让你更加方便使用

点位1:在Bean后处理器的before方法之前(检查Bean是否实现了Aware相关的接口BeanNameAware、BeanClassLoaderAware、BeanFactoryAware)

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

点位2:在Bean后处理器的before方法之后(检查Bean是否实现了InitializingBean接口)

点位3:使用Bean之后或者说销毁Bean之前(检查Bean是否实现了DisposableBean接口)

在这里插入图片描述

User类实现了BeanNameAware, BeanClassLoaderAware, BeanFactoryAware, InitializingBean, DisposableBean5个接口并实现它们的所有方法

  • InitializingBean接口的afterPropertiesSet方法早于init-method的执行 , DisposableBean接口的destroy方法早于destroy-method的执行
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执行");}
}

编写Bean后处理器重写postProcessBeforeInitialization和postProcessAfterInitialization方法

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;}
}

在spring的配置文件中配置Bean后处理器(作用于当前配置文件中所有的Bean),并手动指定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">    <!--这个Bean后处理器将作用于整个配置文件中所有的bean--><bean class="com.powernode.spring6.bean.LogBeanPostProcessor"/><!--手动指定Bean的初始化方法和销毁方法--><bean id="userBean" class="com.powernode.spring6.bean.User" init-method="initBean" destroy-method="destroyBean"><property name="name" value="zhangsan"/></bean>
</beans>

测试结果

public class BeanLifecycleTest {@Testpublic void testLifecycle(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");User userBean = applicationContext.getBean("userBean", User.class);System.out.println("8.使用Bean");// 必须手动关闭Spring容器才会销毁Bean从而执行Bean的销毁方法ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext;context.close();}
}

在这里插入图片描述

Bean的不同管理方式

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

  • 对于singleton作用域的Bean: Spring能够精确地知道该Bean何时被创建,何时初始化完成以及何时被销毁(完整的生命周期)
  • 对于prototype作用域的Bean: Spring只负责Bean的创建, 当客户端程序获取到该Bean后,Spring容器将不再跟踪其生命周期 , 剩下的操作交给客户端管理

将spring配置文件中User类的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"><!--将Bean的作用域设置为多实例的--><bean id="userBean" class="com.powernode.spring6.bean.User" init-method="initBean" destroy-method="destroyBean" scope="prototype"><property name="name" value="zhangsan"/></bean><!--配置Bean后处理器,这个后处理器将作用于当前配置文件中所有的bean--><bean class="com.powernode.spring6.bean.LogBeanPostProcessor"/>
</beans>
public class BeanLifecycleTest {@Testpublic void testLifecycle(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");User userBean = applicationContext.getBean("userBean", User.class);System.out.println("8.使用Bean");// 当客户端程序获取到该Bean后,容器将不再跟踪其生命周期即生命周期方法不再执行,剩下的操作交给客户端管理ClassPathXmlApplicationContext context = (ClassPathXmlApplicationContext) applicationContext;context.close();}
}

在这里插入图片描述

Spring管理自己new的对象

有些时候可能会需要将我们自己new的java对象交给Spring容器管理,此时需要创建默认的DefaultListableBeanFactory工厂对象用来注册Bean并指定Bean的id

// 定义Bean
public class User {
}
public class RegisterBeanTest {@Testpublic void testBeanRegister(){// 自己new的User对象User user = new User();// com.powernode.spring6.bean.User@79e2c065System.out.println(user);// 创建默认列表BeanFactory对象注册BeanDefaultListableBeanFactory factory = new DefaultListableBeanFactory();// 注册Beanfactory.registerSingleton("userBean", user);// 根据id从spring容器中获取beanUser userBean = factory.getBean("userBean", User.class);// com.powernode.spring6.bean.User@79e2c065System.out.println(userBean);}
}

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

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

相关文章

【案例】超声波测距系统设计

1.1 总体设计 1.1.1 概述 学习了明德扬至简设计法和明德扬设计规范&#xff0c;本人用FPGA设计了一个测距系统。该系统采用超声波进行测量距离再在数码管上显示。在本案例的设计过程中包括了超声波的驱动、三线式数码管显示等技术。经过逐步改进、调试等一系列工作后&#xf…

Vue中的常用指令v-html / v-show / v-if / v-else / v-on / v-bind / v-for / v-model

前言 持续学习总结输出中&#xff0c;Vue中的常用指令v-html / v-show / v-if / v-else / v-on / v-bind / v-for / v-model 概念&#xff1a;指令&#xff08;Directives&#xff09;是Vue提供的带有 v- 前缀 的特殊标签属性。可以提高操作 DOM 的效率。 vue 中的指令按照不…

【洛谷 P5019】[NOIP2018 提高组] 铺设道路 题解(分治算法+双指针)

[NOIP2018 提高组] 铺设道路 题目背景 NOIP2018 提高组 D1T1 题目描述 春春是一名道路工程师&#xff0c;负责铺设一条长度为 n n n 的道路。 铺设道路的主要工作是填平下陷的地表。整段道路可以看作是 n n n 块首尾相连的区域&#xff0c;一开始&#xff0c;第 i i i …

Jenkins简介及Docker Compose部署

Jenkins是一个开源的自动化服务器&#xff0c;用于自动化构建、测试和部署软件项目。它提供了丰富的插件生态系统&#xff0c;支持各种编程语言和工具&#xff0c;使得软件开发流程更加高效和可靠。在本文中&#xff0c;我们将介绍Jenkins的基本概念&#xff0c;并展示如何使用…

openssl+sha256开发实例(C++)

文章目录 一、 sha256介绍二、sha256原理三、openssl sha256实现 一、 sha256介绍 SHA-256&#xff08;Secure Hash Algorithm 256-bit&#xff09;是一种哈希算法&#xff0c;属于 SHA-2&#xff08;Secure Hash Algorithm 2&#xff09;家族的一员。SHA-256 产生的哈希值是一…

Redis使用Pipeline(管道)批量处理

Redis 批量处理 在开发中&#xff0c;有时需要对Redis 进行大批量的处理。 比如Redis批量查询多个Hash。如果是在for循环中逐个查询&#xff0c;那性能会很差。 这时&#xff0c;可以使用 Pipeline (管道)。 Pipeline (管道) Pipeline (管道) 可以一次性发送多条命令并在执…

【操作系统】考研真题攻克与重点知识点剖析 - 第 3 篇:内存管理

前言 本文基础知识部分来自于b站&#xff1a;分享笔记的好人儿的思维导图与王道考研课程&#xff0c;感谢大佬的开源精神&#xff0c;习题来自老师划的重点以及考研真题。此前我尝试了完全使用Python或是结合大语言模型对考研真题进行数据清洗与可视化分析&#xff0c;本人技术…

Git 服务器上的 LFS 下载

以llama为例&#xff1a; https://huggingface.co/meta-llama/Llama-2-7b-hf Github # 1. 安装完成后&#xff0c;首先先初始化&#xff1b;如果有反馈&#xff0c;一般表示初始化成功 git lfs install ​ # 2. 如果刚刚下载的那个项目没啥更改&#xff0c;重新下一遍&#x…

TP触摸屏调试

此处以MT6739 1g版本敦泰TP为例(kernel 4.19),主要修改点如下: 1. 两个配置文件defconfig: kernel-4.19\arch\arm\configs\k39tv1_bsp_1g_k419_debug_defconfig: kernel-4.19\arch\arm\configs\k39tv1_bsp_1g_k419_defconfig: CONFIG_INPUT_TOUCHSCREEN=y CONFIG_TOUCHSCRE…

一文了解游戏行业(数据分析)

一.概况 1.基本术语 游戏行业基础术语——持续更新ing... 2.产业链 包括游戏开发&#xff0c;发行和销售等环节 ①游戏开发 上游环节是游戏产业链的核心环节&#xff0c;包括游戏策划&#xff0c;美术设计&#xff0c;程序开发等&#xff0c;是决定游戏质量与内容的关键因…

Leetcode刷题详解—— 有效的数独

1. 题目链接&#xff1a;36. 有效的数独 2. 题目描述&#xff1a; 请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 &#xff0c;验证已经填入的数字是否有效即可。 数字 1-9 在每一行只能出现一次。数字 1-9 在每一列只能出现一次。数字 1-9 在每一个以粗实线分隔的…

sass 封装媒体查询工具

背景 以往写媒体查询可能是这样的&#xff1a; .header {display: flex;width: 100%; }media (width > 320px) and (width < 480px) {.header {height: 50px;} }media (width > 480px) and (width < 768px) {.header {height: 60px;} }media (width > 768px) …

解决ios向mac复制文字不成功的一种方法

### 环境&#xff1a; ios: 16.7.2 macos: 13.6.1 ### 问题现象&#xff1a; 从ios复制了文字&#xff0c;在mac上粘贴总是不成功&#xff0c;总是粘贴出mac上复制的内容。 ### 问题分析&#xff1a; 可能是mac复制的内容优先级比ios复制的内容优先级高&#xff0c;所以不清…

Python实战 | 使用 Python 和 TensorFlow 构建卷积神经网络(CNN)进行人脸识别

专栏集锦&#xff0c;大佬们可以收藏以备不时之需 Spring Cloud实战专栏&#xff1a;https://blog.csdn.net/superdangbo/category_9270827.html Python 实战专栏&#xff1a;https://blog.csdn.net/superdangbo/category_9271194.html Logback 详解专栏&#xff1a;https:/…

链表的逆置

方法1&#xff1a; 依次将指针反向&#xff0c;最后令头指针指向尾元素。 逆置过程如下&#xff1a; 当q指针为空时&#xff0c;循环结束。 //试写一算法&#xff0c;对单链表实现就地逆置&#xff0c; void Reverse1(List plist)//太复杂,不用掌握 {assert(plist ! NULL);i…

Spark Job优化

1 Map端优化 1.1 Map端聚合 map-side预聚合&#xff0c;就是在每个节点本地对相同的key进行一次聚合操作&#xff0c;类似于MapReduce中的本地combiner。map-side预聚合之后&#xff0c;每个节点本地就只会有一条相同的key&#xff0c;因为多条相同的key都被聚合起来了。其他节…

基于轻量级卷积神经网络CNN开发构建打架斗殴识别分析系统

在很多公共场合中&#xff0c;因为一些不可控因素导致最终爆发打架斗殴或者大规则冲突事件的案例层出不穷&#xff0c;基于视频监控等技术手段智能自动化地识别出已有或者潜在的危险行为对于维护公共场合的安全稳定有着重要的意义。本文的核心目的就是想要基于CNN模型来尝试开发…

Mathtype公式自动转Word自带公式

Mathtype公式自动转Word自带公式 前言/word技巧探索过程参考资料&#xff08;有效与无效&#xff09;全自动方案/代码/教程 前言/word技巧 word公式 用ALT号可以输入简单latex显示公式&#xff1b;复杂度&#xff0c;需要引入latex包的不行&#xff1b;显示不出来的话按一下en…

CentOS指令学习

目录 一、常用命令 1、ls 2、cd_pwd 3、touch_mkdir_rmdir_rm 4、cp_mv 5、whereis_which_PATH 6、find 7、grep 8、man_help 9、关机与重启 二、压缩解压 1、zip_unzip 2、gzip_gunzip 3、tar 三、其他指令 1、查看用户登录信息 2、磁盘使用情况 3、查看文件…

本地部署_语音识别工具_Whisper

1 简介 Whisper 是 OpenAI 的语音识别系统&#xff08;几乎是最先进&#xff09;&#xff0c;它是免费的开源模型&#xff0c;可供本地部署。 2 docker https://hub.docker.com/r/onerahmet/openai-whisper-asr-webservice 3 github https://github.com/ahmetoner/whisper…