Spring ApplicationListener使用方法及二次呼叫問題解決

胡海超發表於2018-08-09

使用場景

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

用法

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

package com.secbro.learn.context;

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;

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

 

然後,例項化ApplicationStartListener這個類,在Spring boot中通過一個配置類來進行例項化:

package com.secbro.learn.conf;

import com.secbro.learn.context.ApplicationStartListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Created by zhuzs on 2017/5/12.
 */
@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都被例項化之後才進行呼叫。根據不同的業務場景和需求,可選擇不同的方案來實現。

 

版權宣告:本文為博主原創文章,轉載請寫明出處: https://blog.csdn.net/wo541075754/article/details/71720984

相關文章