Spring Bean初始化之後執行指定方法
轉載:https://blog.csdn.net/forever7107/article/details/76446544
常用的設定方式有以下三種:
通過實現 InitializingBean/DisposableBean 介面來定製初始化之後/銷燬之前的操作方法;
通過 <bean> 元素的 init-method/destroy-method屬性指定初始化之後 /銷燬之前呼叫的操作方法;
在指定方法上加上@PostConstruct 或@PreDestroy註解來制定該方法是在初始化之後還是銷燬之前呼叫。
public class InitSequenceBean implements InitializingBean {
public InitSequenceBean() {
System.out.println("InitSequenceBean: constructor");
}
@PostConstruct
public void postConstruct() {
System.out.println("InitSequenceBean: postConstruct");
}
public void initMethod() {
System.out.println("InitSequenceBean: init-method");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitSequenceBean: afterPropertiesSet");
}
}
並且在配置檔案中新增如下Bean定義:
<bean class="InitSequenceBean" init-method="initMethod"></bean>
輸出結果:
InitSequenceBean: constructor
InitSequenceBean: postConstruct
InitSequenceBean: afterPropertiesSet
InitSequenceBean: init-method
通過上述輸出結果,說明三種初始化的順序是:
Constructor > @PostConstruct > InitializingBean > init-method
原因:
@PostConstruct註解後的方法在BeanPostProcessor前置處理器中就被執行了。我們知道BeanPostProcessor介面是一個回撥的作用,Spring容器的每個受管Bean在呼叫初始化方法之前,都會獲得BeanPostProcessor介面實現類的一個回撥。在BeanPostProcessor的方法中有一段邏輯就是會判斷當前被回撥的bean的方法中有沒有被initAnnotationType/destroyAnnotationType註釋,如果有,則新增到init/destroy佇列中,後續一一執行。initAnnotationType/destroyAnnotationType註解就是@PostConstruct/@PreDestroy。所以@PostConstruct當然要先於InitializingBean和init-method執行了。
從圖中,我們可以看到例項化Bean的過程中有以下幾個節點:
1)設定屬性值;
2)呼叫Bean中的BeanNameAware.setBeanName()方法,如果該Bean實現了BeanNameAware介面;
3)呼叫Bean中的BeanFactoryAware.setBeanFactory()方法,如果該Bean實現了BeanFactoryAware介面;
4)呼叫BeanPostProcessors.postProcessBeforeInitialization()方法;@PostConstruct註解後的方法就是在這裡被執行的
5)呼叫Bean中的afterPropertiesSet方法,如果該Bean實現了InitializingBean介面;
6)呼叫Bean中的init-method,通常是在配置bean的時候指定了init-method,例如:<bean class="beanClass" init-method="init"></bean>
7)呼叫BeanPostProcessors.postProcessAfterInitialization()方法;
8)如果該Bean是單例的,則當容器銷燬並且該Bean實現了DisposableBean介面的時候,呼叫destory方法;如果該Bean是prototype,則將準備好的Bean提交給呼叫者,後續不再管理該Bean的生命週期。