1. 简介
@PreDestroy是java5的时候引入的注解,主要用于标记一个方法,在对象销毁之前执行该方法,被@PreDestroy标记的方法一般用来做一些清理工作,例如关闭一些数据库或者网络的连接,记录一些系统关闭的日志信息等,在Servlet的destroy方法之前执行,只执行一次。
2. API说明
PreDestroy 注解在方法上用作回调通知,以表示实例正在被容器移除。使用 PreDestroy 注释的方法通常用于释放它一直持有的资源。所有支持 PostConstruct 的容器管理对象(Java EE 5 中的应用程序客户端容器除外)都必须支持此注释。应用 PreDestroy 注释的方法必须满足以下所有条件:
-
该方法一定不能有任何参数,除了拦截器的情况,在这种情况下它采用拦截器规范定义的 InvocationContext 对象。
-
拦截器类上定义的方法必须具有以下特征之一:
注意:PreDestroy 拦截器方法不得抛出应用程序异常,但如果同一拦截器方法除了生命周期事件外还干预业务或超时方法,则可以声明它抛出已检查的异常,包括 java.lang.Exception。如果 PreDestroy 拦截器方法返回一个值,容器将忽略该值。 -
非拦截器类上定义的方法必须具有以下特征:
-
应用 PreDestroy 的方法可以是公共的、受保护的、包私有的或私有的
-
该方法一定不能是静态的
-
该方法可以被final修饰
-
如果方法抛出未检查异常,则会被忽略,除非 EJB 可以处理异常
3. Java9及后续版本中的替代方案
J2EE已在Java 9中弃用 @PreDestroy ,并计划在Java 11中将其删除。替代方案通过实现 DisposableBean接口实现或@Bean注解中的 destroyMethod 属性。
- DisposableBean接口:
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyBean implements DisposableBean {
public MyBean() {
System.out.println("构造方法被调用");
}
@Override
public void destroy() {
System.out.println("destroy方法被调用");
}
}
- @Bean注解中的 destroyMethod 属性
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig {
@Bean(destroyMethod = "cleanup")
public MyService myService() {
return new MyService();
}
}
public class MyService {
public void cleanup() {
// 清理资源
System.out.println("MyService 被销毁");
}
}
如果你还是非要在Java 9 及以后的版本使用 @PreDestroy,你也可以手动添加相关依赖。
maven:
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
说明:Java9和Java10中,jdk中仍然有javax.annotation包,Java11开始就没有javax.annotation包,但是在springBoot的项目中,即使没有显示引入javax.annotation包,也能使用@PreDestroy注解,主要是因为spring-boot-starter-web中会间接引入javax.annotation的依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>