Spring ApplicationListener使用方法及問題(onApplicationEvent被調用兩次)

使用場景

在一些業務場景中,當容器初始化完成以後,須要處理一些操做,好比一些數據的加載、初始化緩存、特定任務的註冊等等。這個時候咱們就可使用Spring提供的ApplicationListener來進行操做。java

用法

本文以在Spring boot下的使用爲例來進行說明。首先,須要實現ApplicationListener接口並實現onApplicationEvent方法。把須要處理的操做放在onApplicationEvent中進行處理:spring

package com.secbro.learn.context;
 
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
 
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;
 
 
@Configuration
public class ListenerConfig {
 
    @Bean
    public ApplicationStartListener applicationStartListener(){
        return new ApplicationStartListener();
    }
}

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

個人父容器爲:null
初始化時我被調用了。

從打印的結果能夠看出,ApplicationStartListener的onApplicationEvent方法在容器啓動時已經被成功調用了。而此時初始化的容器爲root容器。app

二次調用問題

此處使用Spring boot來進行操做,沒有出現二次調用的問題。在使用傳統的application.xml和project-servlet.xml配置中會出現二次調用的問題。主要緣由是初始化root容器以後,會初始化project-servlet.xml對應的子容器。咱們須要的是隻執行一遍便可。那麼上面打印父容器的代碼用來進行判斷排除子容器便可。在業務處理以前添加以下判斷:ide

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

這樣其餘容器的初始化就會直接返回,而父容器(Parent爲null的容器)啓動時將會執行相應的業務操做。spa

關聯知識

在spring中InitializingBean接口也提供了相似的功能,只不過它進行操做的時機是在全部bean都被實例化以後才進行調用。根據不一樣的業務場景和需求,可選擇不一樣的方案來實現。code

相關文章
相關標籤/搜索