Spring@PostConstruct和@PreDestroy

时间:2020-02-23 14:35:57  来源:igfitidea点击:

当我们使用依赖注入配置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方法来执行所有资源清除。