Spring 监听器

259 阅读2分钟

起因

spring的监听器在spring容器整个生命流程中起着至关重要的作用,用了springboot以后更是如此,故有了此篇文章。

主要内容

文章分为三部分:

1.spring中简单使用demo演示。

2.监听器源码简单解析。

3.spring自己对于监听器的使用以及我们自己的使用

spring中简单使用demo演示

spring事件

image.png

spring监听器

正常版

image.png

简易版

wenku.baidu.com/view/32e85d… 详细解释

image.png

发布事件

image.png

监听器源码简单解析

大致流程

发布事件后,获取多播器广播事件,根据事件的类型获取对应的监听器,然后调用监听器的onApplicationEvent方法把对应事件传进去。

源码解析

入口 : applicationContext.publishEvent(new YaojieEvent("yaojie"));

image.png

@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
   ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
   Executor executor = getTaskExecutor();
   //getApplicationListeners获取所有的对应事件的监听器 此处不分析getApplicationListeners方法
   for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
      // executor不为null的话就异步执行
      if (executor != null) {
         executor.execute(() -> invokeListener(listener, event));
      }
      else {
         invokeListener(listener, event);
      }
   }
}
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
   ErrorHandler errorHandler = getErrorHandler();
   if (errorHandler != null) {
      try {
         doInvokeListener(listener, event);
      }
      catch (Throwable err) {
         errorHandler.handleError(err);
      }
   }
   else {
      doInvokeListener(listener, event);
   }
}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
   try {
      //调用监听器的onApplicationEvent方法也就是我们重写的方法
      listener.onApplicationEvent(event);
   }
   catch (ClassCastException ex) {
      String msg = ex.getMessage();
      if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
         // Possibly a lambda-defined listener which we could not resolve the generic event type for
         // -> let's suppress the exception and just log a debug message.
         Log logger = LogFactory.getLog(getClass());
         if (logger.isTraceEnabled()) {
            logger.trace("Non-matching event type for listener: " + listener, ex);
         }
      }
      else {
         throw ex;
      }
   }
}

小总结

我们使用spring的监听器非常简单,其实spring自身的监听器实现也很简单,是对观察者模式的巧妙封装与实践,值得细细品味。

spring自己对于监听器的使用以及我们自己的使用

spring自己的简单使用

观察ApplicationEvent的继承结构,发现很多事件继承了它。

image.png

image.png

光观察这些类就知道spring容器各个阶段都在使用着监听器的相关功能。

spring中简单的例子

在spring容器结束刷新的方法中

image.png

image.png

我们自己的使用

我们也可以根据相关业务在spring容器相关阶段处理相关事件。 打个比方,我们登入时一般会把登入相关信息存入redis,但是项目关闭的时候应该清空redis登入相关信息, 就可以监听spring容器ContextStoppedEvent事件,在结束事件中进行相关操作(要调用spring容器相关方法优雅的关闭容器)。

也可以在spring容器启动的时候进行相关操作,一切以实际为准。

本文对于spring监听器做了简单的分析与操作,如有错误请各位大佬指正!!!