一、Spring 生命週期回調機制可選方式
Spring官方文檔註明從Spring 2.5開始,您可以使用三種方式來控制Bean生命週期行爲:
-
自定義
init()
和destroy()
方法
您可以組合以上這些機制來控制給定的 bean。
注:如果爲 bean 配置了多個生命週期機制,並且每個機制配置了不同的方法名稱,則每個配置的方法都按照下面的順序執行。但是,如果配置了相同的方法名稱 - 對於 example,init()
用於初始化方法 - 對於多個這些生命週期機制,該方法將執行一次,如前一節中所述。(--翻譯自原文)
二、各種回調機制方式執行順序
爲同一bean配置的多個生命週期機制,使用不同的初始化方法,調用順序如下:
1、用@PostConstruct
註解的方法
2、由InitializingBean回調接口定義的afterPropertiesSet()方法
3、自定義配置的init()方法(xml中的init-method或者@Bean
的initMethod
屬性)
銷燬方法調用順序相同:
1、用@
PreDestroy註釋的方法
2、由DisposableBean回調接口定義的destroy()方法
3、自定義配置的destroy()方法(xml中的destroy-method或者@Bean
的destroyMethod
屬性)
三、代碼測試
採用xml配置啓動Spring應用(Spring版本爲5.0.5.RELEASE):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--開啓識別註解-->
<context:annotation-config/>
<bean id="x" class="com.dxc.opentalk.springtest.service.X" init-method="customInit"
destroy-method="customDestroy">
</bean>
<bean id="y" class="com.dxc.opentalk.springtest.service.Y"></bean>
</beans>
測試類X:
package com.dxc.opentalk.springtest.service;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
/**
* @author dxc
* @since 2020-02-10
*/
public class X implements InitializingBean, DisposableBean {
@Autowired
private Y y;
private String s;
public X() {
System.out.println("Construct X");
}
/**三種初始化回調方法*/
public void customInit() {
System.out.println("init-method exec...");
}
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean exec...");
}
@PostConstruct
public void annotationInit() {
System.out.println("@PostConstruct exec...");
}
/**三種銷燬回調方法*/
public void destroy() throws Exception {
System.out.println("DisposableBean exec...");
}
public void customDestroy() {
System.out.println("destroy-method exec...");
}
@PreDestroy
public void annotationDestroy() {
System.out.println("@PreDestroy exec...");
}
}
啓動類:
package com.dxc.opentalk.springtest;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author dxc
* @since 2020-02-29
*/
public class XmlBootStrap {
public static void main(String[] args) {
ClassPathXmlApplicationContext applicationContext = new
ClassPathXmlApplicationContext("applicationContext.xml");
//關閉上下文,測試bean銷燬回調方法
applicationContext.close();
}
}
程序運行結果:
Construct X
Construct Y
@PostConstruct exec...
InitializingBean exec...
init-method exec...
@PreDestroy exec...
DisposableBean exec...
destroy-method exec...
可以看出,初始化回調方法以及銷燬回調方法與上述的順序一致。另外,需要說明的是如果這三種方式中的兩個或者三個用到一個方法上,那麼這個方法只會被調用一次。測試如下:
修改xml配置:
<bean id="x" class="com.dxc.opentalk.springtest.service.X" init-method="afterPropertiesSet"
destroy-method="destroy">
</bean>
讓三種方式都配置到一個方法上:
package com.dxc.opentalk.springtest.service;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
/**
* @author dxc
* @since 2020-02-10
*/
public class X implements InitializingBean, DisposableBean {
@Autowired
private Y y;
private String s;
public X() {
System.out.println("Construct X");
}
public void customInit() {
System.out.println("init-method exec...");
}
@PostConstruct
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean exec...");
}
public void annotationInit() {
System.out.println("@PostConstruct exec...");
}
@PreDestroy
public void destroy() throws Exception {
System.out.println("DisposableBean exec...");
}
public void customDestroy() {
System.out.println("destroy-method exec...");
}
public void annotationDestroy() {
System.out.println("@PreDestroy exec...");
}
}
程序運行結果如下:
Construct X
Construct Y
InitializingBean exec...
DisposableBean exec...
可見,這種情況下初始化回調方法和銷燬回調方法都只執行了一次。