Spring@PostConstruct和@PreDestroy
当我们使用依赖注入配置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作用域是"原型",那么它不会完全由spring容器管理,并且不会调用"PreDestroy"方法。
如果有一个名为shutdown或者close的方法,那么当bean被销毁时,spring容器将尝试自动将它们配置为回调方法。
Spring @PostConstruct和@PreDestroy示例
这是带有@PostConstruct和@PreDestroy方法的简单Spring bean。
package com.theitroad.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.theitroad.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.theitroad.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中的原型并运行主类即可。
您将获得如下输出。
MyBean instance created Verifying Resources 1640296160 MyBean instance created Verifying Resources 1863374262
因此很明显,spring容器会在每个请求上初始化Bean,调用其@PostConstruct方法,然后将其移交给客户端。
之后,Spring将不再管理Bean,在这种情况下,客户端必须通过直接调用PreDestroy方法来执行所有资源清除。

