SpringBoot 使用ApplicationListener监听器

11 篇文章 0 订阅
2 篇文章 0 订阅

使用场景

在一些业务场景中,当Serverlet容器初始化完成、重启、关闭等等一系列动作之后,需要处理一些操作,比如一些数据的加载、初始化缓存、特定任务的注册等等。这个时候我们就可以使用Spring提供的ApplicationListener来进行操作。

原理

ApplicationListener是一个接口,里面只有一个onApplicationEvent方法,方法的参数为ApplicationEvent,ApplicationEvent是个抽象类,顾名思义就是Spring应用的一些Event,ApplicationEvent又有一个抽象子类ApplicationContextEvent,这里用到的就是ApplicationContextEvent的实现类。查看ApplicationContextEvent文档的实现类,有ContextClosedEventContextRefreshedEventContextStartedEventContextStoppedEvent,这四个都是spring context包中的核心实现:

 ApplicationEvent
  |-ApplicationContextEvent
    |-ContextClosedEvent:应用关闭事件
    |-ContextRefreshedEvent:应用刷新事件
    |-ContextStartedEvent:应用开启事件
    |-ContextStoppedEvent:应用停止事件

另外:spring boot扩展了两个实现:

    EmbeddedServletContainerInitializedEvent:内嵌Servlet容器初始化事件
    ApplicationReadyEvent:spring Application启动完成事件

用法

本文以在Spring boot下的使用为例来进行说明。首先,需要实现ApplicationListener接口并实现onApplicationEvent方法。把需要处理的操作放在onApplicationEvent中进行处理:

package com.example.springbootlistener.listener;

import lombok.extern.slf4j.Slf4j;

import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.event.ContextStartedEvent;
import org.springframework.context.event.ContextStoppedEvent;
import org.springframework.stereotype.Component;

/**
 * <p>
 * Title: AppApplicationListener
 * </p>
 * <p>
 * Description:
 * </p>
 * <p>
 * Copyright: Copyright (c) 2020
 * </p>
 * <p>
 * </p>
 *
 * @Auther: cw
 * @Date: 2021/12/31 13:23
 */
@Slf4j
@Component
public class AppApplicationListener implements ApplicationListener {


  @Override
  public void onApplicationEvent(ApplicationEvent event) {
    log.info("+++++++++++++++++++++++++++++++++++++++++++++");
    // 容器启动
    if (event instanceof ContextStartedEvent){
      log.info("================:{}", "ContextStartedEvent");
    }
    // 容器刷新
    if (event instanceof ContextRefreshedEvent){
      log.info("================:{}", "ContextRefreshedEvent");
    }
    // 容器关闭
    if (event instanceof ContextClosedEvent){
      log.info("================:{}", "ContextClosedEvent");
    }
    // 容器停止
    if (event instanceof ContextStoppedEvent){
      log.info("================:{}", "ContextStoppedEvent");
    }
    // 容器就绪  ,个人理解 就是启动完成就绪
    if (event instanceof ApplicationReadyEvent){
      log.info("================:{}", "ApplicationReadyEvent");
    }
    log.info(">>>>>>>>>>>>>>>>:{}\n", event.getClass().getName());

  }
}

启动运行结果:

 关闭运行结果:

 

二次调用问题

此处使用Spring boot来进行操作,没有出现二次调用的问题。在使用传统的applicationContext.xml和project-servlet.xml配置中会出现二次调用的问题。主要原因是初始化root容器之后,会初始化project-servlet.xml对应的子容器。我们需要的是只执行一遍即可。那么上面打印父容器的代码用来进行判断排除子容器即可。在业务处理之前添加如下判断:

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

这样其他容器的初始化就会直接返回,而父容器(Parent为null的容器)启动时将会执行相应的业务操作。

关联知识

在spring中InitializingBean接口也提供了类似的功能,只不过它进行操作的时机是在所有bean都被实例化之后才进行调用。根据不同的业务场景和需求,可选择不同的方案来实现。

       代码地址:

https://gitee.com/yulanzhilian.com/mycroot.giticon-default.png?t=LBL2https://gitee.com/yulanzhilian.com/mycroot.git

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值