1. 程式人生 > >Spring 的監聽事件 ApplicationListener 和 ApplicationEvent 用法及呼叫過程詳解

Spring 的監聽事件 ApplicationListener 和 ApplicationEvent 用法及呼叫過程詳解

ApplicationListener呼叫過程詳解:

https://blog.csdn.net/u014263388/article/details/78996509

使用場景
在一些業務場景中,當容器初始化完成之後,需要處理一些操作,比如一些資料的載入、初始化快取、特定任務的註冊等等。這個時候我們就可以使用Spring提供的ApplicationListener來進行操作。

用法
本文以在Spring boot下的使用為例來進行說明。首先,需要實現ApplicationListener介面並實現onApplicationEvent方法。把需要處理的操作放在onApplicationEvent中進行處理:


public class ApplicationStartListener implements ApplicationListener<ContextRefreshedEvent>{
    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        System.out.println("我的父容器為:" + contextRefreshedEvent.getApplicationContext().getParent());
        System.out.println("初始化時我被呼叫了。");
    }
}

然後,例項化ApplicationStartListener這個類,在Spring boot中通過一個配置類來進行例項化:
@Configuration
public class ListenerConfig {

    @Bean
    public ApplicationStartListener applicationStartListener(){
        return new ApplicationStartListener();
    }
}

隨後,啟動Spring boot服務,打印出一下內容:

我的父容器為:null
初始化時我被呼叫了。
從列印的結果可以看出,ApplicationStartListener的onApplicationEvent方法在容器啟動時已經被成功呼叫了。而此時初始化的容器為root容器。

二次呼叫問題
此處使用Spring boot來進行操作,沒有出現二次呼叫的問題。在使用傳統的application.xml和project-servlet.xml配置中會出現二次呼叫的問題。主要原因是初始化root容器之後,會初始化project-servlet.xml對應的子容器。我們需要的是隻執行一遍即可。那麼上面列印父容器的程式碼用來進行判斷排除子容器即可。在業務處理之前新增如下判斷:

if(contextRefreshedEvent.getApplicationContext().getParent() != null){
            return;
}

這樣其他容器的初始化就會直接返回,而父容器(Parent為null的容器)啟動時將會執行相應的業務操作。

關聯知識
在spring中InitializingBean介面也提供了類似的功能,只不過它進行操作的時機是在所有bean都被例項化之後才進行呼叫。根據不同的業務場景和需求,可選擇不同的方案來實現。