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 作用域 是“prototype”,那么它并不完全由 Spring 容器管理,PreDestroy 方法将不会被调用。如果存在一个名为 shutdownclose 的方法,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