Spring Bean有哪些生命周期回调方法?有哪几种实现方式?

你可能想问的是 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 每次获取都是新实例,容器不管理其销毁,需手动处理)。

相关推荐
ITMan彪叔4 分钟前
Nodejs打包 Webpack 中 __dirname 的正确配置与行为解析
javascript·后端
GHOME13 分钟前
Vue2与Vue3响应式原理对比
前端·vue.js·面试
张元清15 分钟前
useMergedRefs: 组件封装必不可少的自定义Hook
前端·javascript·面试
用户895356032822021 分钟前
告别重复,用Go泛型精简Gin代码
后端·gin
运维开发故事29 分钟前
AIOps系列 | 开发一个 K8s Chat 命令行工具
后端
惜鸟31 分钟前
大模型工具/函数调用原理和实践
后端
神毓逍遥kang35 分钟前
nestjs drizzle-orm 构建rbac权限系统
前端·后端
用户298698530141 小时前
如何使用 Spire.Doc 将 Word 转换为 TIFF?
后端
颜如玉1 小时前
位运算技巧总结
后端·算法·性能优化
狗头大军之江苏分军1 小时前
频繁跳槽和稳定工作有什么区别?真的比稳定工作的人差吗?
前端·后端