SpringBoot:Bean生命周期自定义初始化和销毁

在这里插入图片描述

🏡浩泽学编程:个人主页

 🔥 推荐专栏:《深入浅出SpringBoot》《java项目分享》
              《RabbitMQ》《Spring》《SpringMVC》

🛸学无止境,不骄不躁,知行合一

文章目录

  • 前言
  • 一、@Bean注解指定初始化和销毁方法
  • 二、实现InitializingBean接口和DisposableBean接口
  • 三、@PostConstruct(初始化逻辑)和@PreDestroy(销毁逻辑)注解
  • 四、BeanPostProcessor接口
  • 总结


前言

上篇文章详细讲诉了Bean的生命周期和作用域,在生命周期中提到了如何自定义初始化Bean,可能很多人不知道如何自定义初始化,这里详细补充讲解一下:使用@Bean注解指定初始化和销毁方法、实现InitializingBean接口和DisposableBean接口自定义初始化和销毁、@PostConstruct(初始化逻辑)和@PreDestroy(销毁逻辑)注解、使用BeanPostProcessor接口。


一、@Bean注解指定初始化和销毁方法

  • 创建BeanTest类,自定义初始化方法和销毁方法。
  • 在@Bean注解的参数中指定BeanTest自定义的初始化和销毁方法:
  • 销毁方法只有在IOC容器关闭的时候才调用。

代码如下:

/**
 * @Version: 1.0.0
 * @Author: Dragon_王
 * @ClassName: dog
 * @Description: TODO描述
 * @Date: 2024/1/21 22:55
 */
public class BeanTest {
    public BeanTest(){
        System.out.println("BeanTest被创建");
    }

    public void init(){
        System.out.println("BeanTest被初始化");
    }

    public void destory(){
        System.out.println("BeanTest被销毁");
    }
}
/**
 * @Version: 1.0.0
 * @Author: Dragon_王
 * @ClassName: MyConfig
 * @Description: TODO描述
 * @Date: 2024/1/21 22:59
 */
@Configuration
@ComponentScan(("com.dragon.restart1"))
public class MyConfig {
    @Bean(initMethod = "init",destroyMethod = "destory")
    public BeanTest beanTest(){
        return new BeanTest();
    }
}
//测试代码
AnnotationConfigApplicationContext ct = new AnnotationConfigApplicationContext(MyConfig.class);
System.out.println("IoC容器创建完成");

在这里插入图片描述

  • 可以看到调用的是自定义的方法,这里解释一下,测试时,运行完代码块程序就结束了,所哟IoC容器就被关闭,所以调用了IoC销毁方法。同时可以看到初始化方法在对象创建完成后调用。
  • 当组件的作用域为单例时在容器启动时即创建对象,而当作用域为原型(PROTOTYPE)时在每次获取对象的时候才创建对象。并且当作用域为原型(PROTOTYPE)时,IOC容器只负责创建Bean但不会管理Bean,所以IOC容器不会调用销毁方法。

二、实现InitializingBean接口和DisposableBean接口

看一下两接口的方法:

public interface InitializingBean {

	/**
	 * Invoked by the containing {@code BeanFactory} after it has set all bean properties
	 * and satisfied {@link BeanFactoryAware}, {@code ApplicationContextAware} etc.
	 * <p>This method allows the bean instance to perform validation of its overall
	 * configuration and final initialization when all bean properties have been set.
	 * @throws Exception in the event of misconfiguration (such as failure to set an
	 * essential property) or if initialization fails for any other reason
	 * Bean都装配完成后执行初始化
	 */
	void afterPropertiesSet() throws Exception;
}
====================================================================
public interface DisposableBean {

	/**
	 * Invoked by the containing {@code BeanFactory} on destruction of a bean.
	 * @throws Exception in case of shutdown errors. Exceptions will get logged
	 * but not rethrown to allow other beans to release their resources as well.
	 */
	void destroy() throws Exception;

}

代码如下:

/**
 * @Version: 1.0.0
 * @Author: Dragon_王
 * @ClassName: BeanTest1
 * @Description: TODO描述
 * @Date: 2024/1/21 23:25
 */
public class BeanTest1 implements InitializingBean, DisposableBean {
    @Override
    public void destroy() throws Exception {
        System.out.println("BeanTest1销毁");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("BeanTest1初始化");
    }

    public BeanTest1() {
        System.out.println("BeanTest1被创建");
    }
}
=========================

@Configuration
@ComponentScan(("com.dragon.restart1"))
public class MyConfig {
 @Bean
    public BeanTest1 beanTest1(){
        return new BeanTest1();
    }
}

在这里插入图片描述

三、@PostConstruct(初始化逻辑)和@PreDestroy(销毁逻辑)注解

  • 被@PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器调用一次,类似于Serclet的inti()方法。
  • 被@PostConstruct修饰的方法会在构造函数之后,init()方法之前运行。
  • 被@PreDestroy修饰的方法会在服务器卸载Servlet的时候运行,并且只会被服务器调用一次,类似于Servlet的destroy()方法。被@PreDestroy修饰的方法会在destroy()方法之后运行,在Servlet被彻底卸载之前。

代码如下:

/**
 * @Version: 1.0.0
 * @Author: Dragon_王
 * @ClassName: BeanTest2
 * @Description: TODO描述
 * @Date: 2024/1/21 23:32
 */
public class BeanTest2 {
    public BeanTest2(){
        System.out.println("BeanTest2被创建");
    }

    @PostConstruct
    public void init(){
        System.out.println("BeanTest2被初始化");
    }

    @PreDestroy
    public void destory(){
        System.out.println("BeanTest2被销毁");
    }
}
========================
//
@Configuration
@ComponentScan(("com.dragon.restart1"))
public class MyConfig {
 @Bean
    public BeanTest2 beanTest2(){
        return new BeanTest2();
    }
}

在这里插入图片描述

四、BeanPostProcessor接口

BeanPostProcessor又叫Bean的后置处理器,是Spring框架中IOC容器提供的一个扩展接口,在Bean初始化的前后进行一些处理工作。

BeanPostProcessor的源码如下:

public interface BeanPostProcessor {

	/**
	 * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
	 * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
	 * or a custom init-method). The bean will already be populated with property values.
	 * The returned bean instance may be a wrapper around the original.
	 * <p>The default implementation returns the given {@code bean} as-is.
	 * @param bean the new bean instance
	 * @param beanName the name of the bean
	 * @return the bean instance to use, either the original or a wrapped one;
	 * if {@code null}, no subsequent BeanPostProcessors will be invoked
	 * @throws org.springframework.beans.BeansException in case of errors
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
	 */
	@Nullable
	  //bean初始化方法调用前被调用
	default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	/**
	 * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
	 * initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
	 * or a custom init-method). The bean will already be populated with property values.
	 * The returned bean instance may be a wrapper around the original.
	 * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
	 * instance and the objects created by the FactoryBean (as of Spring 2.0). The
	 * post-processor can decide whether to apply to either the FactoryBean or created
	 * objects or both through corresponding {@code bean instanceof FactoryBean} checks.
	 * <p>This callback will also be invoked after a short-circuiting triggered by a
	 * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
	 * in contrast to all other BeanPostProcessor callbacks.
	 * <p>The default implementation returns the given {@code bean} as-is.
	 * @param bean the new bean instance
	 * @param beanName the name of the bean
	 * @return the bean instance to use, either the original or a wrapped one;
	 * if {@code null}, no subsequent BeanPostProcessors will be invoked
	 * @throws org.springframework.beans.BeansException in case of errors
	 * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
	 * @see org.springframework.beans.factory.FactoryBean
	 */
	@Nullable
	//bean初始化方法调用后被调用
	default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

代码如下:

/**
 * @Version: 1.0.0
 * @Author: Dragon_王
 * @ClassName: MyBeanPostProcess
 * @Description: TODO描述
 * @Date: 2024/1/21 23:40
 */
@Component
public class MyBeanPostProcess implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization..."+beanName+"=>"+bean);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization..."+beanName+"=>"+bean);
        return bean;
    }
}
============================
@Configuration
@ComponentScan(("com.dragon.restart1"))
public class MyConfig {
    @Bean
    public BeanTest1 beanTest1(){
        return new BeanTest1();
    }

    @Bean
    public BeanTest2 beanTest2(){
        return new BeanTest2();
    }
}

运行结果如下:

BeanTest1被创建
postProcessBeforeInitialization...beanTest1=>com.dragon.restart1.BeanTest1@111d5c97
BeanTest1初始化
postProcessAfterInitialization...beanTest1=>com.dragon.restart1.BeanTest1@111d5c97
BeanTest2被创建
postProcessBeforeInitialization...beanTest2=>com.dragon.restart1.BeanTest2@29c17c3d
BeanTest2被初始化
postProcessAfterInitialization...beanTest2=>com.dragon.restart1.BeanTest2@29c17c3d
IoC容器创建完成
BeanTest2被销毁
BeanTest1销毁

通过上述运行结果可以发现使用BeanPostProcessor的运行顺序为
IOC容器实例化Bean---->调用BeanPostProcessor的postProcessBeforeInitialization方法---->调用bean实例的初始化方法---->调用BeanPostProcessor的postProcessAfterInitialization方法。


总结

以上就是Bean生命周期自定义初始化和销毁的讲解。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android:JNI实战,理论详解、Java与Jni数据调用

一.概述 上一篇博文讲解了如何搭建一个可以加载和链接第三方库、编译C/C文件的Jni Demo App。 这篇博文在这个Jni Demo App的基础上&#xff0c;从实战出发详细讲解 Jni 开发语法。 接下来&#xff0c;先用一小节将Jni开发比较重要的理论知识点过一下&#xff0c;然后进行代…

深入解析Python中的break、continue和pass语句

在Python编程中&#xff0c;控制流语句是一种常见的工具&#xff0c;用于控制程序的执行顺序和流程。其中&#xff0c;break、continue和pass语句是控制循环的重要组成部分。本文将深入解析Python中的break、continue和pass语句&#xff0c;包括其基本语法、应用场景和最佳实践…

万字长文详解Java线程池面试题

王有志&#xff0c;一个分享硬核 Java 技术的互金摸鱼侠 加入 Java 人的提桶跑路群&#xff1a;共同富裕的Java人 今天是《面霸的自我修养》第 6 篇文章&#xff0c;我们一起来看看面试中会问到哪些关于线程池的问题吧。数据来源&#xff1a; 大部分来自于各机构&#xff08;J…

【数据分享】2023年我国省市县三级的住宿服务设施数量(Excel/Shp格式)

宾馆酒店、旅馆招待所等住宿服务设施的配置情况是一个城市公共基础设施完善程度的重要体现&#xff0c;一个城市住宿服务设施种类越丰富&#xff0c;数量越多&#xff0c;通常能表示这个城市的公共服务水平越高&#xff01; 本次我们为大家带来的是我国各省份、各地级市、各区…

38-WEB漏洞-反序列化之PHPJAVA全解(下)

WEB漏洞-反序列化之PHP&JAVA全解&#xff08;下&#xff09; 一、Java中API实现二、序列化理解三、案例演示3.1、本地3.2、Java 反序列化及命令执行代码测试3.3、WebGoat_Javaweb 靶场反序列化测试3.4、2020-网鼎杯-朱雀组-Web-think_java 真题复现 四、涉及资源 一、Java中…

LLM + RecSys 初体验(上)

最近在逛小红书的时候&#xff0c;发现了一个新的GPU算力租赁平台&#xff0c;与AutoDL和恒源云等平台类似。正巧&#xff0c;官网有活动&#xff0c;注册即送RTX 4090三个小时&#xff0c;CPU 5 小时。正巧最近在测试 LLM推荐系统的 OpenP5 平台&#xff0c;果断入手测试! 用…

【Android】细数Linux和Android系统中的伪文件系统

文章目录 前言Linux伪文件系统cgroupfsLinux的cgroupsAndroid的cgroups debugfsfunctionfs(/dev/usb-ffs/adb)functionfs 的引入sysfs是什么 procfs(/proc)pstore(/sys/fs/pstore)selinuxfs(/sys/fs/selinux)sysfs(/sys)参考 前言 做了好些年Android开发&#xff0c;你了解过L…

【GitHub项目推荐--Awesome-Go/Python/JavaScript/Java】【转载】

Awesome 译为令人惊叹的、极好的&#xff0c;GitHub 上有很多 Awesome 开头的开源项目。比如 Awesome-Go、Awesome-Python。 就像汇总常用的软件一样&#xff0c;GitHub上有大量的开源项目&#xff0c;开发者就会根据需要汇总一些常用的好用的资源&#xff0c;并且根据 Awesom…

oracle 19c rac集群管理 ------ 日志管理

oracle 19C rac 数据库的目录结构及日志路径 在Oracle 19c RAC&#xff08;Real Application Clusters&#xff09;集群中&#xff0c;有多个组件和层级生成的日志文件&#xff0c;记录着集群的活动、事件和错误信息&#xff0c;用于故障诊断、性能优化和集群管理。以下是常见…

nvm安装与使用教程

目录 nvm是什么 nvm安装 配置环境变量 更换淘宝镜像 安装node.js版本 nvm list available 显示可下载版本的部分列表 nvm install 版本号 ​编辑 nvm ls 查看已经安装的版本 ​编辑 nvm use 版本号(切换想使用的版本号) nvm是什么 nvm是node.js version management的…

社区公益培训系统功能说明

社区公益培训系统功能说明 本系统将用于社区面向居民开展的公益培训课程展示&#xff0c;在线报名&#xff0c;并按班级排课上课&#xff0c;上课时学员要扫码签到&#xff0c;经常旷课的学员将禁止再报名其他课程。 1. 用户注册与登录 - 提供用户注册和登录功能&#xff0c;…

【LeetCode】每日一题 2024_1_22 最大交换(模拟)

文章目录 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01;题目&#xff1a;最大交换题目描述&#xff1a;代码与解题思路 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01; 几百年没有见到题目描述这么短的题目了&#xff0c;泪目了 题目&#x…

LeetCode 48 旋转图像

题目描述 旋转图像 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4…

java.lang.IllegalArgumentException: When allowCredentials is true

1.遇到的错误 java.lang.IllegalArgumentException: When allowCredentials is true, allowedOrigins cannot contain the special value "*" since that cannot be set on the "Access-Control-Allow-Origin" response header. To allow credentials to a…

gif动图怎么快速生成?这一招快速生成

很多从事新媒体行业的小伙伴都知道在编写公众号的时候会插入一些gif动图来增加与读者的互动。很多时候我们使用的动图都是网上下载的。其实&#xff0c;我们是可以自己制作动图的&#xff0c;下面就来教大家一招如何制作gif动态图片&#xff08;https://www.gif.cn/&#xff09…

C++大学教程(第九版)6.38汉诺塔问题

文章目录 题目代码运行截图 题目 (汉诺塔问题)在这一章中大家了解了既可以用递归方法又可以用迭代方法很容易实现的函数。不过&#xff0c;在这道练习题中&#xff0c;我们提出的问题若用递归来解决&#xff0c;则尽显递归之优雅:若用迭代来实现&#xff0c;恐怕没那么容易。 …

Gold-YOLO(NeurIPS 2023)论文与代码解析

paper&#xff1a;Gold-YOLO: Efficient Object Detector via Gather-and-Distribute Mechanism official implementation&#xff1a;https://github.com/huawei-noah/Efficient-Computing/tree/master/Detection/Gold-YOLO 存在的问题 在过去几年里&#xff0c;YOLO系列已经…

9个提高开发效率的 VS Code技巧

本文就来分享 10 个极大提高开发效率的 VS Code 技巧&#xff01; 标签换行 在VS Code中&#xff0c;可以在设置中搜索"** Editor: Wrap Tabs**"来实现选项卡换行的功能。 这样&#xff0c;在大型项目中工作时&#xff0c;就不需要像在浏览器中一样滚动来查找选项卡…

springcloud Hystrix断路器

文章目录 代码下载简介写服务测试高并发测试写消费者端测试2 服务降级先修改cloud-provider-hystrix-payment8001修改cloud-consumer-feign-hystrix-order80 目前问题方法2:测试 服务熔断实操测试 服务监控hystrixDashboard建mudlue断路器演示(服务监控hystrixDashboard) 代码下…

Vivado开发FPGA使用流程、教程 verilog(建立工程、编译文件到最终烧录的全流程)

目录 一、概述 二、工程创建 三、添加设计文件并编译 四、线上仿真 五、布局布线 六、生成比特流文件 七、烧录 一、概述 vivado开发FPGA流程分为创建工程、添加设计文件、编译、线上仿真、布局布线&#xff08;添加约束文件&#xff09;、生成比特流文件、烧录等步骤&a…