
历史文章(累计400+篇文章)
扩展点系列之SmartInstantiationAwareBeanPostProcessor确定执行哪一个构造方法 - 432篇
扩展点系列之ApplicationContextAwareProcessor普通类获取Spring Bean - 第433篇
扩展点系列之初始化之@PostConstruct、init-method、InitializingBean - 第434篇
SpringBoot/Spring扩展点系列之FactoryBean让你不在懵逼 - 第435篇
SpringBoot/Spring扩展点系列之SmartInitializingSingleton - 第436篇
扩展点系列之CommandLineRunner和ApplicationRunner实现缓存预热 - 第437篇
悟纤:师傅,你看哦,我想在Spring销毁的时候做些内存销毁,我应该怎么做呐?

师傅:巧了,今天我正要讲一下初始化和销毁的3种办法。
悟纤:师傅,那真是太好了,讲完了我刚好就可以用上了。

师傅:徒儿,你知道,对于技术学好的学习方法是什么?
悟纤:我想应该就是实践吧。
师傅:对,如果你要快速的掌握一个技术点,那么最好的方式就是在实际项目中进行实践使用,这样项目能够倒逼你来深入的学习技术。
悟纤:实践出真知,践践更聪明。
师傅:你又贫嘴了,你这话会让人误解~实践出真知,磨炼长才干。
师傅:
读万卷书不如行万里路,
行万里路不如阅人无数,
阅人无数不如名师指路,
名师指路不如贵人相助。

悟纤:师傅,你不仅是我的名师,还是我的贵人,那我不得起飞了~ 我要飞的更高,飞的更高。
师傅:飞的太高,摔得更疼….

导读
有时需要在 Bean 属性值 set 好之后和 Bean 销毁之前做一些事情,比如检查 Bean 中某个属性是否被正常的设置好值。Spring 框架提供了多种方法,让我们可以在 Spring Bean 的生命周期中执行 initialization 和 pre-destroy 方法,比如我们做一些数据的加载执行,链接注册中心暴漏RPC接口以及在Web程序关闭时执行链接断开,内存销毁等操作。
一、初始化和销毁方法概述
1.1 3种实现方式
(1)第一种,通过 @PostConstruct 和 @PreDestroy 方法 实现初始化和销毁 bean 之前进行的操作。
(2)第二种,通过 在 xml 中定义 init-method和 destory-method 方法。
(3)第三种,通过 bean 实现 InitializingBean和DisposableBean 接口。

说明:方式1和2,可以算是一种,只是不同的写法而已。
1.2 对Spring版本的要求
(1)xml和实现接口的方式是Spring最原始的方式,Spring任何版本均支持
(2)@PostConstruct和@PreDestroy需要Spring2.5及以上版本
(3)@bean :需要Spring 3.0以上版本支持
1.3 执行顺序不一样
先看下Spring中bean生命周期:

可以看出先后的执行顺序如下:
(1)初始化之后执行顺序: @PostConstruct > InitializingBean > Bean init-method(xml注解或者@Bean)
(2)销毁之前执行顺序:@preDestroy > DisposableBean > destroy-method(xml注解或者@Bean)
二、初始化和销毁的扩展方式
对于初始化部分的代码查看之前的文章:
《扩展点系列之初始化之@PostConstruct、init-method、InitializingBean - 第434篇》
在这里我们主要看一下销毁的扩展方式。
2.1 @PreDestroy
注解@PreDestroy是javax里定义的,属于JSR-250规范的一部分。
注: @PreDestroy已经从jdk 11版本开始移除了,所以在使用时需要额外引入javax.annotation-api:
<dependency> <groupId>javax.annotationgroupId> <artifactId>javax.annotation-apiartifactId> <version>1.3.2version>dependency>
使用方法就是类的方法上添加注解@PreDestroy,那么是否允许注解多个方法呢?答案是可以的,看如下执行效果:

具体的代码如下:
/** * 使用@PreDestroy */@PreDestroypublic void preDestroy(){ System.out.println("DemoService5.preDestroy [@PreDestroy]");}/** * 使用@PreDestroy */@PreDestroypublic void preDestroy1(){ System.out.println("DemoService5.preDestroy1 [@PreDestroy]");}
2.2 @Bean init-method
在早期的Spring的版本使用xml实现,如
@Bean(destroyMethod = "destroyMethod")public DemoService5 DemoService5(){ return new DemoService5();}
对于这种实现方式,我们会发现需要额外的@Configuration来声明一个@Bean。
如果对于使用@Service、@Controller等这样的方式注入Bean的,那么这种实现方案,就有点爱莫能助了。
destroyMethod就是原来spring配置文件里bean标签上的destroy-method,这个方法需要在DemoService5类中进行定义:
/** * 使用@Bean(destroyMethod = "destroyMethod") */public void destroyMethod(){ System.out.println("DemoService5.destroyMethod [destroyMethod]");}
2.3实现DisposableBean接口
DisposableBean是springframework下的一个类,和Spring框架算是深度捆绑了,但这一点根本不重要。对于使用很简单,就是实现接口DisposableBean:
package com.kfit.demo.service;import org.springframework.beans.factory.DisposableBean;import javax.annotation.PreDestroy;/** * 测试销毁. * * @author 悟纤「公众号SpringBoot」 * @date 2022-08-08 * @slogan 大道至简 悟在天成 */public class DemoService5 implements DisposableBean { /** * 使用implements DisposableBean * @throws Exception */ @Override public void destroy() { System.out.println("DemoService5.destroy [DisposableBean]"); }}
说明:对于类DemoService5可以使用@Service、@Component注入bean。
- 我就是我,是颜色不一样的烟火。
- 我就是我,是与众不同的小苹果。
à悟空学院:https://t.cn/Rg3fKJD
学院中有Spring Boot相关的课程!点击「阅读原文」进行查看!
SpringBoot视频:http://t.cn/A6ZagYTi
SpringBoot交流平台:https://t.cn/R3QDhU0
SpringSecurity5.0视频:http://t.cn/A6ZadMBe
ShardingJDBC分库分表:http://t.cn/A6ZarrqS
分布式事务解决方案:http://t.cn/A6ZaBnIr
JVM内存模型调优实战:http://t.cn/A6wWMVqG
Spring入门到精通:https://t.cn/A6bFcDh4
大话设计模式之爱你:https://dwz.cn/wqO0MAy7