@PreDestroy是最常用、最直观的Bean销毁前清理方式,用于Spring容器关闭或Bean被移除时执行轻量级收尾工作,如关闭连接、释放流、注销监听器等,需注意包路径(javax.annotation或jakarta.annotation)、方法须为public无参void且非static。

在 Java Spring 应用中,@PreDestroy 是最常用、最直观的 Bean 销毁前清理方式。它会在 Spring 容器关闭或该 Bean 被主动移除时自动调用,适合做连接关闭、流释放、监听器注销等轻量级收尾工作。
确保依赖和注解可用
Spring 默认支持 @PreDestroy,但需注意:该注解来自 javax.annotation(Java EE)或 jakarta.annotation(Jakarta EE),不同 JDK 和 Spring 版本对应不同包:
- JDK 8–11 + Spring 5.x:通常用
javax.annotation.PreDestroy - JDK 17+ + Spring 6.x/Boot 3.x:必须改用
jakarta.annotation.PreDestroy - 若编译报错“cannot find symbol”,请检查是否引入了对应依赖,例如 Jakarta 版本需添加:
implementation 'jakarta.annotation:jakarta.annotation-api'
正确声明清理方法
被 @PreDestroy 标记的方法必须满足以下条件,否则 Spring 会忽略它:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 方法名任意,但必须是 public、无参数、返回 void
- 不能是 static 或 final 方法
- 建议加空值和状态判断,避免重复执行或 NPE,例如:
if (conn != null && !conn.isClosed()) { conn.close(); } - 不要抛出受检异常(如
SQLException),应捕获并记录日志;运行时异常可抛出,但不推荐——可能中断销毁流程
典型资源清理示例
常见需要释放的资源类型及写法要点:
立即学习“Java免费学习笔记(深入)”;
-
数据库连接:优先调用
close(),并检查连接状态,防止已关闭再关 -
文件/网络输入输出流:使用 try-with-resources 更安全;若流在 Bean 中长期持有,
@PreDestroy中显式close() -
定时任务(ScheduledTask):调用
taskScheduler.shutdown()或task.cancel(true) -
缓存引用或监听器:从全局缓存 Map 中
remove(this),或调用eventPublisher.removeApplicationListener(...)
替代方案与选用建议
除了 @PreDestroy,Spring 还提供其他销毁机制,适用场景略有差异:
-
实现
DisposableBean接口:适合老项目或需统一抽象销毁逻辑的场景,但侵入性强、灵活性低 -
@Bean(destroyMethod = "xxx"):适用于第三方类(无法加注解),可绑定任意已有关闭方法,如@Bean(destroyMethod = "shutdown") - XML 配置的
destroy-method:已基本淘汰,仅维护旧系统时遇到 - 不推荐在销毁方法中做远程调用、长时间阻塞操作,会影响容器整体关闭速度

















