如何在Spring中使用注解配置Bean的生命周期回调方法?

在 Spring 中使用注解配置 Bean 生命周期回调是最简洁、最主流的方式(替代传统 XML 配置和实现接口的方式),核心围绕 初始化回调销毁回调 两类注解展开。我会用「核心注解 + 完整示例 + 注意事项」的方式,帮你快速掌握注解配置的方法。

一、核心注解介绍

Spring 提供了 3 种主流注解来配置生命周期回调(优先级从高到低):

注解 作用 适用场景 核心特点
@PostConstruct 初始化回调(Bean 就绪前) 初始化资源(连接、配置加载) JSR-250 标准注解,解耦 Spring
@PreDestroy 销毁回调(Bean 销毁前) 释放资源(关闭连接、线程池) JSR-250 标准注解,解耦 Spring
@Bean(initMethod/destroyMethod) 初始化 / 销毁回调 兼容老代码、第三方类(无法加注解) 基于 @Bean 注解配置,灵活度高

注:@PostConstruct@PreDestroy 是 JDK 标准注解(JSR-250),无需依赖 Spring 特定接口,是开发首选。

二、完整代码示例

下面通过 2 个场景(自定义类 + 第三方类)演示注解配置方式:

场景 1:自定义 Bean(直接加 @PostConstruct/@PreDestroy

这是最常用的场景,直接在 Bean 的方法上标注注解即可。

复制代码
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

// 1. 注册为 Spring Bean(@Component 或 @Service/@Repository 等)
@Component
public class DataSourceBean {

    // 无参构造器(Spring 实例化 Bean 时执行)
    public DataSourceBean() {
        System.out.println("步骤1:Bean 实例化(执行构造器)");
    }

    // 2. 初始化回调(属性赋值完成后执行)
    @PostConstruct
    public void initDataSource() {
        System.out.println("步骤2:执行 @PostConstruct 初始化(创建数据库连接)");
        // 自定义逻辑:初始化数据库连接、加载配置、参数校验等
    }

    // 业务方法(Bean 就绪后调用)
    public void queryData() {
        System.out.println("步骤3:Bean 就绪(执行业务方法)");
    }

    // 3. 销毁回调(容器关闭前执行)
    @PreDestroy
    public void closeDataSource() {
        System.out.println("步骤4:执行 @PreDestroy 销毁(关闭数据库连接)");
        // 自定义逻辑:关闭连接、释放线程池、清理缓存等
    }
}
场景 2:第三方类 / 无法加注解的 Bean(用 @Bean 配置 init/destroy 方法)

如果 Bean 是第三方库的类(无法修改源码加注解),可以通过 @BeaninitMethoddestroyMethod 属性指定回调方法。

复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

// 模拟第三方类(无法修改源码,不能加 @PostConstruct/@PreDestroy)
class ThirdPartyConnection {
    // 自定义初始化方法(无参数、无返回值)
    public void initConnection() {
        System.out.println("第三方类:执行初始化(创建连接)");
    }

    // 自定义销毁方法(无参数、无返回值)
    public void closeConnection() {
        System.out.println("第三方类:执行销毁(关闭连接)");
    }

    public void doWork() {
        System.out.println("第三方类:执行业务逻辑");
    }
}

// 配置类
@Configuration
public class BeanConfig {

    // 注册第三方类为 Bean,并指定初始化/销毁方法
    @Bean(
        initMethod = "initConnection",   // 指定初始化回调方法名
        destroyMethod = "closeConnection" // 指定销毁回调方法名
    )
    public ThirdPartyConnection thirdPartyConnection() {
        return new ThirdPartyConnection();
    }
}
场景 3:测试类(验证回调执行)
复制代码
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan(basePackages = "com.example") // 扫描@Component 注解的 Bean
public class LifecycleTest {
    public static void main(String[] args) {
        // 1. 启动 Spring 容器(触发 Bean 实例化、初始化)
        AnnotationConfigApplicationContext context = 
            new AnnotationConfigApplicationContext(LifecycleTest.class);

        // 2. 获取 Bean 并执行业务方法
        DataSourceBean dataSourceBean = context.getBean(DataSourceBean.class);
        dataSourceBean.queryData();

        ThirdPartyConnection thirdPartyConnection = context.getBean(ThirdPartyConnection.class);
        thirdPartyConnection.doWork();

        // 3. 关闭容器(触发 Bean 销毁回调)
        context.close();
    }
}
执行结果(验证顺序)
复制代码
步骤1:Bean 实例化(执行构造器)
步骤2:执行 @PostConstruct 初始化(创建数据库连接)
第三方类:执行初始化(创建连接)
步骤3:Bean 就绪(执行业务方法)
第三方类:执行业务逻辑
步骤4:执行 @PreDestroy 销毁(关闭数据库连接)
第三方类:执行销毁(关闭连接)

三、关键注意事项

  1. 注解方法的要求

    • @PostConstruct/@PreDestroy 标注的方法:无参数、无返回值、访问修饰符任意(public/private 均可),不能抛出检查型异常(RuntimeException 可抛)。
    • @BeaninitMethod/destroyMethod 指定的方法:要求同上,方法名必须和类中定义的一致。
  2. 销毁回调的生效条件

    • 只有 单例 Bean 会执行销毁回调(Spring 容器关闭时触发);
    • 原型 Bean(@Scope("prototype"))由用户手动管理,容器不会调用销毁方法。
  3. 依赖问题

    • @PostConstruct 方法执行时,当前 Bean 的所有属性已经完成赋值,可安全使用依赖的其他 Bean;
    • 不要在构造器中调用依赖的 Bean(此时依赖未注入,会报空指针),优先用 @PostConstruct
  4. JDK 版本兼容

    • JDK 9+ 移除了 JSR-250 注解(@PostConstruct/@PreDestroy),需要手动引入依赖:

      <dependency> <groupId>jakarta.annotation</groupId> <artifactId>jakarta.annotation-api</artifactId> <version>2.1.1</version> </dependency>

总结

  1. 首选方式 :自定义 Bean 直接用 @PostConstruct(初始化)和 @PreDestroy(销毁),解耦且简洁;
  2. 兼容场景 :第三方类 / 无法加注解的 Bean,用 @Bean(initMethod/destroyMethod) 指定回调方法;
  3. 核心规则:销毁回调仅对单例 Bean 生效,注解方法需满足「无参、无返回值」要求。
相关推荐
一直都在5721 小时前
Spring面经
java·后端·spring
闻哥2 小时前
深入Redis的RDB和AOF两种持久化方式以及AOF重写机制的分析
java·数据库·spring boot·redis·spring·缓存·面试
jgyzl2 小时前
2026.3.12 常见的缓存读写策略
java·后端·spring
ruanyongjing2 小时前
Spring TransactionTemplate 深入解析与高级用法
java·数据库·spring
fengxin_rou2 小时前
[Redis从零到精通|第六篇]:Redis的主从同步
java·数据库·redis·缓存
zhglhy2 小时前
Java系统限流方法技术优劣
java·限流
xiaoye37082 小时前
Spring Bean 生命周期
java·spring
6+h3 小时前
【Spring】Bean的生命周期详解
java·python·spring
冬夜戏雪3 小时前
面经摘录(五)
java·后端·spring