Spring事件监听器源码

Spring 自定义了继承 JDK 事件监听器的接口ApplicationListener<E extends ApplicationEvent> extends EventListener,用来监听 Spring 应用程序中的事件;自定义了继承 JDK 事件对象的抽象类ApplicationEvent extends EventObject,用来表示 Spring 应用程序中的事件类型。容器启动刷新过程中,可以定义事件监听器,来监听应用程序上下文事件ApplicationContextEvent extends ApplicationEvent,它有四个具体的实现类:
ContextStartedEvent/ContextRefreshedEvent/ContextStoppedEvent/ContextClosedEvent,分别表示容器启动/刷新/停止/关闭的事件。

通常有两种方式来实现 Spring 中的事件监听:

1.实现 ApplicationListener 接口

public class MyListener implements ApplicationListener<ApplicationEvent> {
    @Override
    public void onApplicationEvent(ApplicationEvent event) {
        System.out.println("MyListener: " + event);
    }
}

2.使用 @EventListener 注解

public class MyAnnotationListener {
    @EventListener(classes = ApplicationEvent.class)
    public void listen(ApplicationEvent event) {
        System.out.println("@EventListener:" + event);
    }
}

3.自定义发布事件

public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Test.class);
        // 发布事件
        context.publishEvent(new ApplicationEvent("my event") {});
    }

}

原理

在 Spring 容器启动,调用 refresh() 刷新的过程中,会初始化事件派发器,并注册事件监听器,最后通过事件派发器,将事件发布给自己的监听器。

1 初始化事件派发器

initApplicationEventMulticaster();

为容器中的 BeanFactory 初始化一个事件派发器 (ApplicationEventMulticaster) :SimpleApplicationEventMulticaster,并注册到 BeanFactory,name 为 applicationEventMulticaster。

2 添加 ApplicationListener 监听器

registerListeners();

取出 BeanFactory 中 ApplicationListener 类型的事件监听器,全部添加到上面的事件派发器的缓存中。

3 添加 @EventListener 监听器

finishBeanFactoryInitialization(beanFactory)

Spring 后置处理器源码 可知,Spring 初始化时会注册 EventListenerMethodProcessor 和 DefaultEventListenerFactory。

EventListenerMethodProcessor 实现了 EventListenerMethodProcessor,所以执行 BeanFactory 后置处理器时,会调用 postProcessBeanFactory(),将 DefaultEventListenerFactory 添加到缓存中。

EventListenerMethodProcessor 实现了 SmartInitializingSingleton,所以在初始化剩余的单例 Bean 之后,会调用 afterSingletonsInstantiated(),获取所有的 BeanFactory,找到其中标注了 @EventListener 的方法,利用反射和 DefaultEventListenerFactory 为其创建 ApplicationListener,并添加到事件派发器的缓存中。

4 发布事件

finishRefresh();

  1. 初始化生命周期处理器,注册到 BeanFactory,name 为 lifecycleProcessor。
  2. 调用生命周期处理器的 onRefresh(),表示刷新状态。
  3. 发布上下文刷新事件。调用事件派发器的 multicastEvent() 进行派发,最终,通过回调事件监听器的 onApplicationEvent() 方法,来通知监听器。

异步派发和异常处理器

  • 如果事件派发器设置了 Executor,则可以进行异步多线程的事件派发。
  • 如果事件派发器设置了 ErrorHandler,则可以用异常处理器来处理异常。

原文地址:https://www.cnblogs.com/bigshark/p/11331245.html

时间: 2024-08-30 07:28:58

Spring事件监听器源码的相关文章

spring 事件模式 源码导读

一,jdk 事件对象基类 package java.util; import java.io.Serializable; public class EventObject implements Serializable { protected transient Object source; public Object getSource() { return this.source; } public EventObject(Object paramObject) { if (paramObj

Spring IOC 容器源码分析

前言: Spring 最重要的概念是 IOC 和 AOP,本篇文章其实就是要带领大家来分析下 Spring 的 IOC 容器.既然大家平时都要用到 Spring,怎么可以不好好了解 Spring 呢?阅读本文并不能让你成为 Spring 专家,不过一定有助于大家理解 Spring 的很多概念,帮助大家排查应用中和 Spring 相关的一些问题. 阅读建议:读者至少需要知道怎么配置 Spring,了解 Spring 中的各种概念,少部分内容我还假设读者使用过 SpringMVC.本文要说的 IOC

Spring Developer Tools 源码分析:二、类路径监控

在 Spring Developer Tools 源码分析一中介绍了 devtools 提供的文件监控实现,在第二部分中,我们将会使用第一部分提供的目录监控功能,实现对开发环境中 classpath 的监控. 二.类路径监控 首先看一些这一部分可能涉及到的类图: 在图中,红色斜线左上部分是第一部分中介绍的文件目录监控的类,其中 FileSystemWatcher 会通过独立线程监控指定的目录,当目录内容发生变化时,通过对比快照可以获得所有监控目录变化的文件ChangedFiles,然后将变化通知

Spring Boot 启动源码解析系列六:执行启动方法一

1234567891011121314151617181920212223242526272829303132333435363738394041424344 public ConfigurableApplicationContext (String... args) { StopWatch stopWatch = new StopWatch(); // 开始执行,记录开始时间 stopWatch.start(); ConfigurableApplicationContext context =

Spring mvc之源码 handlerMapping和handlerAdapter分析

Spring mvc之源码 handlerMapping和handlerAdapter分析 本篇并不是具体分析Spring mvc,所以好多细节都是一笔带过,主要是带大家梳理一下整个Spring mvc的执行流程,以及如何根据URL查找处理器Controller的实现 (适合那些刚阅读源码不知道如何下手的人) http://www.guojinbao.com/borrow/borrowDetail/GETadLPjnf0[d].do 如何根据URL地址---->找到正确处理器Controller

spring framework 4 源码阅读 --- 前期准备

在开始看代码之前,需要做的第一件事是下载代码. 在这里:https://github.com/spring-projects/spring-framework 下载完成了发现使用gradle做的源代码的构建管理工具的. 值得庆幸的事情,spring为导入eclipse写了脚本工具,包解压后结构如下: 发现了一个脚本文件:import-into-eclipse.bat,今天负责导入的就是他了, 等待漫长的编译,这里有个问题,在没有安装gradle的时候,脚本会自动下载gradle 执行完成后是这样

Spring AOP高级——源码实现(1)动态代理技术

在正式进入Spring AOP的源码实现前,我们需要准备一定的基础也就是面向切面编程的核心——动态代理. 动态代理实际上也是一种结构型的设计模式,JDK中已经为我们准备好了这种设计模式,不过这种JDK为我们提供的动态代理有2个缺点: 只能代理实现了接口的目标对象: 基于反射,效率低 鉴于以上2个缺点,于是就出现了第二种动态代理技术——CGLIB(Code Generation Library).这种代理技术一是不需要目标对象实现接口(这大大扩展了使用范围),二是它是基于字节码实现(这比反射效率高

Spring AOP高级——源码实现(2)Spring AOP中通知器(Advisor)与切面(Aspect)

本文例子完整源码地址:https://github.com/yu-linfeng/BlogRepositories/tree/master/repositories/Spring%20AOP%E9%AB%98%E7%BA%A7%E2%80%94%E2%80%94%E6%BA%90%E7%A0%81%E5%AE%9E%E7%8E%B0%EF%BC%882%EF%BC%89Spring%20AOP%E4%B8%AD%E9%80%9A%E7%9F%A5%E5%99%A8%EF%BC%88Advisor

Spring Core Container 源码分析三:Spring Beans 初始化流程分析

前言 本文是笔者所著的 Spring Core Container 源码分析系列之一: 本篇文章主要试图梳理出 Spring Beans 的初始化主流程和相关核心代码逻辑: 本文转载自本人的私人博客,伤神的博客: http://www.shangyang.me/2017/04/01/spring-core-container-sourcecode-analysis-beans-instantiating-process/ 本文为作者的原创作品,转载需注明出处: 源码分析环境搭建 参考 Sprin