Spring的@PostConstruct和@PreDestroy
当我们使用依赖注入配置Spring Beans时,有时我们希望在我们的Bean开始为客户端请求提供服务之前确保一切都初始化正确。同样地,当上下文被销毁时,我们可能需要关闭一些由Spring Bean使用的资源。
春天的@PostConstruct
当我们用@SpringBean的@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或更低版本,则无需添加上述依赖项。
春天的 @PreDestroy
当我们使用PreDestroy注解对一个Spring Bean方法进行注解时,当bean实例从上下文中移除时,该方法将被调用。理解这一点非常重要-如果您的Spring Bean作用域为“prototype”,那么它并不完全由Spring容器管理,PreDestroy方法将不会被调用。如果存在名为shutdown或close的方法,Spring容器将尝试在销毁bean时自动配置它们作为回调方法。
Spring @PostConstruct和@PreDestroy示例
这是一个带有@PostConstruct和@PreDestroy方法的简单的Spring bean。
package com.Olivia.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.Olivia.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();
}
}
我不需要明确地将我的bean指定为单例,但我将在后续将其值更改为“prototype”,并查看在@PostConstruct和@PreDestroy方法中发生的情况。这是我的主类,我在其中创建了Spring上下文并获取了几个MyBean的实例。
package com.Olivia.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
只需将MyConfiguration中的scope值更改为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代码库中查看完整的项目代码。