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方法来执行所有资源清除。