當我們使用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
的方法,那麼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
所以 @PostConstruct 方法是在bean实例化后调用的。当上下文关闭时,它会同时调用shutdown和close方法。
Spring @PostConstruct 和 @PreDestroy 与Prototype范围
只需将 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