Spring框架生命周期注解详解:@PostConstruct与@PreDestroy使用指南

当我们使用依赖注入配置Spring Beans时,有时我们希望在我们的Bean开始为客户端请求提供服务之前确保一切都初始化正确。同样地,当上下文被销毁时,我们可能需要关闭一些由Spring Bean使用的资源。

Spring的@PostConstruct

当我们使用@PostConstruct注解来标注一个Spring Bean的方法时,该方法会在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方法将不会被自动调用。此外,如果Bean中存在名为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方法被调用。当应用程序上下文关闭时,Spring会同时调用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实例,在这种情况下,客户端必须负责通过直接调用相应的清理方法来完成所有资源的清理工作。

总结

@PostConstruct和@PreDestroy是与Spring Bean生命周期管理相关的重要注解。我们可以使用它们来验证Bean是否被正确初始化,并在Bean从Spring应用程序上下文中移除时关闭所有资源。

您可以从我们的GitHub代码仓库中查看完整的项目代码。

bannerAds