PostConstruct 和 PreDestroy 注解
1、简介
Spring 允许我们在 Bean 的创建和销毁时执行自定义操作。例如,可以让 Bean 实现 InitializingBean
和 DisposableBean
接口,从而在创建和销毁时触发回调方法。
本文将带你了解第二种实现方式,即使用 @PostConstruct
和 @PreDestroy
注解。
2、@PostConstruct
Spring 只会在 Bean 属性初始化后调用一次注解了 @PostConstruct
的方法。即使没有任何属性需要初始化,这些方法也会运行。
使用 @PostConstruct
注解的方法可以用任何访问级别,但不能是静态的。
@PostConstruct
一个可能的用途是填充数据。例如,在开发过程中,我们想创建一些默认用户:
@Component
public class DbInit {
@Autowired
private UserRepository userRepository;
@PostConstruct
private void postConstruct() {
// 初始化默认用户
User admin = new User("admin", "admin password");
User normalUser = new User("user", "user password");
userRepository.save(admin, normalUser);
}
}
上述示例将首先初始化 UserRepository
属性,然后运行 @PostConstruct
方法。
3、@PreDestroy
在 Spring 将 Bean 从 Application Context 中删除之前,会运行一次注解了 @PreDestroy
的方法。
与 @PostConstruct
一样,注解为 @PreDestroy
的方法可以有任何访问级别,但不能是静态的。
@Component
public class UserRepository {
private DbConnection dbConnection;
@PreDestroy
public void preDestroy() {
// 释放 DB 连接
dbConnection.close();
}
}
该方法的目的应该是在 Bean 被销毁之前释放资源或执行其他清理任务,如关闭数据库连接。
4、用 javax.annotation 还是 jakarta.annotation?
从 JDK 6 到 JDK 8,@PostConstruct
和 @PreDestroy
注解是标准 Java 库中 javax.annotation
包的一部分。但是,从 JDK 9 开始,整个 javax.annotation
包从核心 Java 模块中移除,并在 JDK 11 中完全取消。在 Jakarta EE 9 中,该包被重新命名为 jakarta.annotation
。
因此,到底应该使用 javax.annotation
还是 jakarta annotation
的注解?这取决于使用的 Spring 版本。
Spring、JDK、javax 和 jakarta 命名空间之间的兼容性如下表:
Spring 版本 | JDK 版本 | Java / Jakatar 命名空间 |
---|---|---|
6.1.x | JDK 17 to JDK 23 | jakarta |
6.0.x | JDK 17 to JDK 21 | jakarta |
5.3.x | JDK 8 to JDK 21 | javax |
如上表所示,在 Spring 6.0.x 和 6.1.x 中,我们应使用 jakarta
命名空间。但是,如果我们的项目使用了 Spring 5.3.x 和 JDK 9 或更高版本,由于 Spring 5.3.x 仅支持 javax
命名空间,我们必须在项目中明确添加 javax.annotation-api
依赖:
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
5、总结
本文介绍了如何使用 @PostConstruct
和 @PreDestroy
注解来在 Bean 的初始化和销毁时执行回调方法,还介绍了 Spring、JDK、javax 和 jakarta 命名空间之间的兼容性。
Ref:https://www.baeldung.com/spring-postconstruct-predestroy