构造方法 → @PostConstruct 方法 → 业务逻辑 → @PreDestroy 方法 → 对象销毁
@PreDestroy
生命周期管理的注解,它属于 Java 规范(JSR-250)中定义的注解,@PreDestroy
依赖容器的支持(如 Spring、Java EE 容器),如果对象是通过 new
手动创建的(非容器托管),注解不会生效
-
作用时机
被@PreDestroy
标记的方法,会在对象即将被容器(如 Spring 容器、EJB 容器)销毁之前调用。具体时机因容器而异:- 在 Spring 中,当单例 bean 被容器销毁(如容器关闭)时触发。
- 在 Java EE 中,当托管对象(如 EJB、CDI bean)被容器移除时触发。
-
方法要求
- 注解只能标记在非静态方法上。
- 方法可以有任意访问修饰符(
public
、protected
、private
)。 - 方法不能有参数,且返回值必须为
void
。 - 方法不能抛出受检异常(checked exception),但可以抛出非受检异常(unchecked exception)。
-
依赖关系
如果多个 bean 之间存在依赖关系,容器会先调用依赖对象的@PreDestroy
方法,再调用当前对象的@PreDestroy
方法,确保资源释放的顺序正确。
@PostConstruct
JAVA类静态资源 需要手动释放吗,JVM停止时会自动释放这些资源吗
JVM 停止(进程终止)时,操作系统会回收进程占用的系统级资源(如内存、文件描述符、网络端口等),但应用级资源(如逻辑连接、线程池状态等)需要手动处理,否则可能导致中间状态异常(如未完成的任务、数据不一致)。
线程池 / 线程 | ExecutorService | 调用 shutdown() 或 shutdownNow() |
数据库连接池 | HikariCP 、Druid | 调用 close() 关闭连接池 |
网络连接 | Socket 、HttpClient | 调用 close() 关闭连接 |
文件流 | FileInputStream | 调用 close() 或使用 try-with-resources |
分布式资源 | 分布式锁、缓存连接 | 释放锁、关闭缓存客户端 |
如何正确手动释放静态资源?
根据运行环境,可通过以下方式释放静态资源:
-
通用场景(非容器环境):
注册 JVM 关闭钩子(Shutdown Hook
),在 JVM 终止前执行释放逻辑:public class StaticResourceHolder { private static final ExecutorService executor = Executors.newFixedThreadPool(5); static { // 注册关闭钩子 Runtime.getRuntime().addShutdownHook(new Thread(() -> { System.out.println("释放静态线程池..."); executor.shutdown(); // 优雅关闭线程池 })); } }
-
Spring 容器环境:
利用 Spring 的生命周期回调(如@PreDestroy
),在容器关闭时释放:@Component public class StaticResourceManager { private static final HikariDataSource dataSource = new HikariDataSource(); // Spring 容器关闭时触发 @PreDestroy public void closeDataSource() { dataSource.close(); // 关闭数据库连接池 } }
-
手动调用释放方法:
在程序逻辑结束处(如main
方法末尾)显式调用释放方法:public class App { private static final SomeResource resource = new SomeResource(); public static void main(String[] args) { try { // 业务逻辑 } finally { resource.close(); // 手动释放 } } }
如果直接通过 kill
命令(如 kill -9
)强制终止 JVM 进程,所有资源释放逻辑(如 @PreDestroy
方法、JVM 关闭钩子 Shutdown Hook
等)都不会被执行。
kill -15
(默认信号 SIGTERM):属于 “温和终止”,会通知 JVM 进程准备退出。此时 JVM 会触发关闭钩子(Shutdown Hook
)、@PreDestroy
等资源释放逻辑,然后正常退出
kill -9
(信号 SIGKILL):属于 “强制终止”,操作系统会直接终止进程,不会给 JVM 任何执行清理逻辑的机会,所有资源释放代码都不会运行。