当我们使用依赖注入配置Spring Beans时,有时我们希望在我们的Bean开始为客户端请求提供服务之前确保一切都已正确初始化。类似地,当上下文被销毁时,我们可能需要关闭一些Spring Bean使用的资源。
Spring @PostConstruct
当我们在Spring Bean中的方法上注解@PostConstruct
时,它会在Spring Bean初始化后执行。我们只能有一个方法被@PostConstruct
注解标注。这个注解是Common Annotations API的一部分,也是JDK模块javax.annotation-api
的一部分。所以如果你在Java 9或以上版本中使用这个注解,你需要显式地将这个jar包添加到你的项目中。如果你使用的是maven,则应该添加以下依赖项。
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
如果你使用的是Java 8或更低版本,则无需添加上述依赖。
Spring @PreDestroy
当我们使用 `PreDestroy` 注解标记一个 Spring Bean 方法时,它会在 bean 实例从上下文中移除时被调用。这是一个非常重要的点要理解 – 如果你的 spring bean 作用域 是“prototype”,那么它并不完全由 Spring 容器管理,PreDestroy
方法将不会被调用。如果存在一个名为 shutdown
或 close
的方法,Spring 容器将尝试在销毁 bean 时自动配置它们作为回调方法。
Spring @PostConstruct 和 @PreDestroy 示例
这是一个带有 @PostConstruct 和 @PreDestroy 方法的简单 Spring Bean 示例。
package com.journaldev.spring;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class MyBean {
public MyBean() {
System.out.println("MyBean instance created");
}
@PostConstruct
private void init() {
System.out.println("Verifying Resources");
}
@PreDestroy
private void shutdown() {
System.out.println("Shutdown All Resources");
}
public void close() {
System.out.println("Closing All Resources");
}
}
请注意,我还定义了一个 close
方法来检查在销毁我们的 bean 时是否被调用。这是我的简单的 spring 配置 类。
package com.journaldev.spring;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
@Configuration
public class MyConfiguration {
@Bean
@Scope(value="singleton")
public MyBean myBean() {
return new MyBean();
}
}
I don’t need to explicitly specify my bean as a singleton but I will later change its value to “prototype” and see what happens with @PostConstruct and @PreDestroy methods. Here is my main class where I am creating spring context and getting few instances of MyBean.
package com.journaldev.spring;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MySpringApp {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(MyConfiguration.class);
ctx.refresh();
MyBean mb1 = ctx.getBean(MyBean.class);
System.out.println(mb1.hashCode());
MyBean mb2 = ctx.getBean(MyBean.class);
System.out.println(mb2.hashCode());
ctx.close();
}
}
当我们运行上述类时,我们会得到以下输出。
MyBean instance created
Verifying Resources
1640296160
1640296160
Shutdown All Resources
Closing All Resources
所以,在实例化Bean后调用@PostConstruct方法。当上下文关闭时,它会同时调用shutdown和close方法。
Spring @PostConstruct和@PreDestroy与Prototype Scope一起使用
只需将MyConfiguration
中的作用域值更改为prototype,然后运行主类。您将获得如下输出。
MyBean instance created
Verifying Resources
1640296160
MyBean instance created
Verifying Resources
1863374262
因此清楚地表明,Spring容器正在初始化每个请求的Bean,调用其@PostConstruct方法,然后将其交给客户端。在这种情况下,Spring不再管理Bean,客户端必须通过直接调用PreDestroy方法来执行所有资源清理。
摘要
@PostConstruct和@PreDestroy是与Spring Bean生命周期管理一起使用的重要注解。我们可以使用它们来验证bean是否正确初始化,然后在bean从Spring上下文中移除时关闭所有资源。
您可以从我们的GitHub存储库检查完整的项目代码。
Source:
https://www.digitalocean.com/community/tutorials/spring-postconstruct-predestroy