@PreDestroy 是 Spring 中用于 Bean 销毁前执行轻量级清理的注解,仅对容器管理的 Bean 生效,要求方法 void、无参、非 static、访问符任意且唯一,Singleton 在上下文关闭时触发,Prototype 默认不触发。

@PreDestroy 是 Spring 中用于在 Bean 销毁前执行清理逻辑的标准注解,适合做轻量级资源释放,比如关闭连接、清空缓存、停止线程池等。但它不是“一贴就灵”的万能钩子,必须满足几个关键前提才能生效。
必须是 Spring 容器管理的 Bean
手动 new 出来的对象、工具类静态实例、或未被 Spring 扫描/注册的类,加了 @PreDestroy 也完全不会调用。只有通过以下方式声明的 Bean 才可能触发:
- @Component、@Service、@Repository、@Controller 等组件注解(且包路径被 @ComponentScan 覆盖)
- @Bean 方法注册的实例(默认 singleton,prototype 需额外处理)
- @Configuration 类中显式配置的托管组件
方法签名必须严格合规
@PreDestroy 标注的方法不能随便写,否则 Spring 会忽略它,甚至启动失败:
- 返回类型必须是 void
- 不能有参数(零参数)
- 不能是 static 方法
- 访问修饰符可以是 private、package-private、protected 或 public
- 一个类里只能有一个 @PreDestroy 方法
示例正确写法:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
import javax.annotation.PreDestroy;@Component
public class DatabaseConnectionManager {
private Connection conn;
@PreDestroy
public void closeConnection() {
if (conn != null && !conn.isClosed()) conn.close();
}
}
销毁时机取决于 Bean 作用域和上下文生命周期
@PreDestroy 不会在任意时刻自动调用,它的触发依赖容器行为:
- Singleton Bean:只在 ApplicationContext 正常关闭时触发(如调用 context.close() 或 Spring Boot 应用优雅停机)
- Prototype Bean:默认不触发 —— Spring 不负责原型 Bean 的销毁,需手动调用或通过 registerDisposableBean 注册后才可响应
- 强制终止无效:kill -9、断电、进程崩溃等场景下,JVM 直接退出,@PreDestroy 绝对不会执行
替代方案与补充建议
如果 @PreDestroy 不够灵活,或需要更可控的销毁流程,可考虑这些方式:
- 实现 DisposableBean 接口:重写 destroy() 方法,语义明确,Spring 原生支持
- @Bean(destroyMethod = "xxx"):在配置类中为第三方类指定销毁方法(如 Apache HttpClient 的 close())
- 显式管理:对关键资源(如线程池),在业务代码中调用 shutdown(),不完全依赖容器回调
注意:所有清理操作应尽量轻量、快速、避免阻塞;不要在 @PreDestroy 里做耗时 IO、远程调用或等待锁。

















