如何在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 是第三方库的类(无法修改源码加注解),可以通过 @Bean 的 initMethod 和 destroyMethod 属性指定回调方法。

复制代码
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 可抛)。
    • @Bean 的 initMethod/destroyMethod 指定的方法:要求同上,方法名必须和类中定义的一致。
  2. 销毁回调的生效条件:

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

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

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

      jakarta.annotation jakarta.annotation-api 2.1.1

总结

  1. 首选方式 :自定义 Bean 直接用 @PostConstruct(初始化)和 @PreDestroy(销毁),解耦且简洁;
  2. 兼容场景 :第三方类 / 无法加注解的 Bean,用 @Bean(initMethod/destroyMethod) 指定回调方法;
  3. 核心规则:销毁回调仅对单例 Bean 生效,注解方法需满足「无参、无返回值」要求。
相关推荐
代码不停1 小时前
自动化测试(java)
java·开发语言·selenium·自动化
唠点键盘之外的2 小时前
26 向量数据库实战:从 0 搭一条能用的检索链路(pgvector + Spring AI)
数据库·人工智能·spring
鬼手点金3 小时前
opencode-rules 插件
java·开发语言·前端·人工智能·chrome·git·github
paopaokaka_luck4 小时前
滑雪场管理系统(AI智能助手流式对话,ECharts 运营数据分析、教练、雪具与场地一体化预约,钱包支付退款、订单核销与服务评价)
java·人工智能·spring boot·网络协议·数据分析·echarts
考虑考虑4 小时前
@JsonInclude注解使用
spring boot·后端·spring
Wang's Blog4 小时前
Java 项目实战: 交友项目 - Dubbo 的内部结构与一次调用的完整链路
java·dubbo
Wang's Blog4 小时前
Java 项目实战: 交友项目 - Dubbo 入门引导
java·dubbo·交友
蜗牛互联网5 小时前
Python Agent工具调用的白名单、参数校验与审批门禁
java·服务器·前端·人工智能·后端·python
SL_staff5 小时前
当规则引擎开始‘懂业务’:JVS-Rules金融风控四大原生能力拆解
java·python·全栈
Shaoshing5 小时前
前缀和与差分
java·数据结构·算法·前缀和·差分