你可能想问的是 Spring Bean 的生命周期回调方法。Spring Bean 生命周期回调是指 Bean 在初始化完成后、销毁前由 Spring 容器自动调用的方法,用于执行自定义逻辑(如资源初始化、释放连接等)。
一、核心生命周期回调方法
主要包含两类核心回调:
1.初始化回调:Bean 实例化(构造器调用)和属性注入完成后,Spring 自动调用,用于执行初始化逻辑(如初始化数据库连接池、加载配置文件)。
2.销毁回调:Bean 被容器销毁前(如容器关闭时),Spring 自动调用,用于执行资源释放逻辑(如关闭连接、释放文件句柄)。
二、回调方法的 4 种实现方式
1. 实现 Spring 提供的接口(接口回调)
通过实现 InitializingBean(初始化)和 DisposableBean(销毁)接口,重写固定方法,Spring 会自动识别并调用。
初始化:实现 InitializingBean 接口,重写 afterPropertiesSet() 方法(属性注入完成后调用)。
销毁:实现 DisposableBean 接口,重写 destroy() 方法(容器销毁 Bean 前调用)。
示例代码1:
csharp
@Component
public class Book implements InitializingBean, DisposableBean {
private String title;
//空参
public Book() {
System.out.println("1.实例化 Book 对象");
}
//set
@Value("Java 编程思想")
public void setTitle(String title) {
this.title = title;
System.out.println("2.依赖注入(属性填充) 设置 Book 对象的 title 属性,title = " + title);
}
//get
public String getTitle() {
return title;
}
//初始化方法
public void myInit() {
if (title == null) {
title = "默认书籍"; // 如果没有设置标题,则使用默认标题
System.out.println("3.3 自定义初始化方法 Book 对象> 默认标题是:" + title);
} else {
System.out.println("3.3 自定义初始化方法 Book 对象> 标题是:" + title);
}
}
//自定义初始化方法 PostConstruct
@PostConstruct
public void customInit() {
System.out.println("3.1 PostConstruct初始化方法init1 Book 对象 -- init");
}
//自定义销毁方法
@PreDestroy
public void customDestroy() {
System.out.println("5.1 Book 对象 -- PreDestroy");
}
//销毁方法
public void myDestroy() {
System.out.println("5.3 自定义销毁方法 Book 对象");
}
// InitializingBean 接口的方法
public void afterPropertiesSet() throws Exception {
System.out.println("3.2 InitializingBean初始化方法 Book 对象 -- afterPropertiesSet");
if (title == null) {
title = "默认书籍"; // 如果没有设置标题,则使用默认标题
// System.out.println("4.1 初始化方法 Book 对象> 默认标题是:" + title);
} else {
// System.out.println("4.1 初始化方法 Book 对象> 标题是:" + title);
}
}
// DisposableBean 接口的方法
public void destroy() throws Exception {
System.out.println("5.2 销毁方法 Book 对象 -- DisposableBean");
// 在这里可以执行一些清理操作,例如关闭资源等
}
}
2. 配置文件/注解指定自定义方法(自定义方法回调)
无需实现接口,而是通过 XML 配置或注解(@Bean)指定自定义的初始化/销毁方法名,Spring 会反射调用这些方法。
初始化方法:自定义任意方法(无参数、无返回值),通过配置指定为初始化回调。
销毁方法:自定义任意方法(无参数、无返回值),通过配置指定为销毁回调。
示例 1:XML 配置
xml
<!-- 配置 Bean,指定 init-method(初始化)和 destroy-method(销毁) -->
<!-- 定义一个book bean-->
<bean id="book" class="com.example.demo.bean.Book" init-method="myInit" destroy-method="myDestroy">
<property name="title" value="Java编程思想"/>
</bean>
示例 2:@Bean 注解配置
less
@Configuration // 使用 @Configuration 注解标记该类为配置类
@ComponentScan(basePackages = "com.example.demo.bean") // 扫描指定包下的组件
public class AppConfig {
@Bean(initMethod = "myInit", destroyMethod = "myDestroy") // 定义一个 Bean,并指定初始化和销毁方法
public Book book() {
return new Book();
}
}
// 自定义回调方法的 Bean
csharp
public class Book {
private String title;
//初始化方法
public void myInit() {
if (title == null) {
title = "默认书籍"; // 如果没有设置标题,则使用默认标题
System.out.println("3.3 自定义初始化方法 Book 对象> 默认标题是:" + title);
} else {
System.out.println("3.3 自定义初始化方法 Book 对象> 标题是:" + title);
}
}
//销毁方法
public void myDestroy() {
System.out.println("5.3 自定义销毁方法 Book 对象");
}
// setter/getter 略
}
3. 使用 JSR-250 标准注解(注解回调)
通过 JSR-250 规范定义的 @PostConstruct(初始化)和 @PreDestroy(销毁)注解,直接标记在方法上,Spring 会自动扫描并调用(需确保 Spring 支持注解驱动,如配置 context:annotation-config/ 或 @ComponentScan)。
@PostConstruct:标记在初始化方法上,Bean 实例化+属性注入完成后调用。
@PreDestroy:标记在销毁方法上,Bean 被容器销毁前调用。
示例代码:
typescript
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Component // 确保 Bean 被 Spring 扫描管理
public class Book {
private String title;
//自定义初始化方法 PostConstruct
@PostConstruct
public void customInit() {
System.out.println("3.1 PostConstruct初始化方法init1 Book 对象 -- init");
}
//自定义销毁方法
@PreDestroy
public void customDestroy() {
System.out.println("5.1 Book 对象 -- PreDestroy");
}
// setter/getter 略
}
4. 实现 BeanPostProcessor 接口(全局后置处理器)
BeanPostProcessor 是 Spring 的"Bean 后置处理器",作用于所有 Bean 的生命周期,可在 Bean 初始化前后插入自定义逻辑(注意:这是"全局回调",影响容器内所有 Bean,而非单个 Bean 的回调)。
postProcessBeforeInitialization:在 Bean 的初始化方法(如 afterPropertiesSet()、@PostConstruct)执行 前 调用。
postProcessAfterInitialization:在 Bean 的初始化方法执行 后 调用。
示例代码:
typescript
@Component
public class BookProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
// 在初始化之前执行
if (bean instanceof Book) {
System.out.println("2.5 -- Before Initialization: " + beanName);
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
// 在初始化之后执行
if (bean instanceof Book) {
System.out.println("3.5 -- After Initialization: " + beanName);
}
return bean;
}
}
测试接口:
csharp
@Test
public void test4() {
// 测试类
//通过注解的方式生成bean的测试
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
// 获取 book 对象
Book book = context.getBean(Book.class);
// 4.使用bean
// System.out.println("8.使用Bean Cat 对象,name = " + cat.getName());
System.out.println("4.使用Bean Book 对象,name = " + book.getTitle());
// 关闭容器
context.close();
// 5.销毁 Cat 对象
// 注意:在使用 ClassPathXmlApplicationContext 时,销毁方法会在 close() 方法调用时自动执行
}
测试结果如下:
lua
1.实例化 Book 对象
2.依赖注入(属性填充) 设置 Book 对象的 title 属性,title = Java 编程思想
2.5 -- Before Initialization: book
3.1 PostConstruct初始化方法init1 Book 对象 -- init
3.2 InitializingBean初始化方法 Book 对象 -- afterPropertiesSet
3.3 自定义初始化方法 Book 对象> 标题是:Java 编程思想
3.5 -- After Initialization: book
4.使用Bean Book 对象,name = Java 编程思想
5.1 Book 对象 -- PreDestroy
5.2 销毁方法 Book 对象 -- DisposableBean
5.3 自定义销毁方法 Book 对象
三、关键注意点
1.执行顺序(以单个 Bean 为例):
构造器调用 → 属性注入 → BeanPostProcessor.postProcessBeforeInitialization → 初始化回调(@PostConstruct/afterPropertiesSet()/自定义 init 方法) → BeanPostProcessor.postProcessAfterInitialization → Bean 就绪 → 容器关闭 → 销毁回调(@PreDestroy/destroy()/自定义 destroy 方法)。
2.销毁回调生效场景:仅单例 Bean 的销毁回调会被 Spring 自动调用(原型 Bean 每次获取都是新实例,容器不管理其销毁,需手动处理)。