Spring Event 实现原理

转载:Spring Event 实现原理

1. Demo

1.1 事件定义

继承 ApplicationEvent 类

import lombok.Getter;
import org.springframework.context.ApplicationEvent;

@Getter
public class EventDemo extends ApplicationEvent {

    private String message;
    
    // Object source 具体事件源类
    public EventDemo(Object source, String message) {
        super(source);
        this.message = message;
    }
}

1.2 事件监听

实现 ApplicationListener 类,并重写 onApplicationEvent() 方法

1.3 事件发布

ApplicationEventPublisher Bean 发布事件

2. 源码分析

2.1 事件是如何发送的?

从 demo 的代码来看 事件是通过 ApplicationEventPublisher 类的 publishEvent() 方法发送的;那么通过断点追踪此方法的行为轨迹,我们会发现其实是调用了 AbstractApplicationContext 类的 publishEvent() 方法,那么请看下面的源码。

既然找到了发送事件的入口,那么就先追踪 applicationEventMulticaster() 方法

到这里我们只掌握了 ApplicationEventMulticaster 是个接口类,并不知道真正的实现类,而且也没发现关于此接口的构造函数(稍后再揭秘实现类究竟是怎么来的);但是通过断点追踪 multicastEvent() 方法,不难发现其实是调用了 SimpleApplicationEventMulticaster 类的 multicastEvent(),源码如下:

  1. 走到这里我们会发现事件的监听者都来自 getApplicationListeners(event, type);

  2. 通知监听者的其实是 invokeListener(listener, event);

2.2 揭秘如何获取事件对应的监听者

这里同样也会产生一个问题。我们知道 listeners 取自内部类 ListenerRetriever 维护的 applicationListeners 对象,那么 applicationListeners 何时 add 了呢?稍后再揭秘。

总结 获取所有 ApplicationListener 的实现类后,依次判断是否支持给定的事件,也就是事件的类型是否一致;最终通过特定的 cachKey 放置缓存。

2.3 揭秘如何通知事件的监听者

核心代码:listener.onApplicationEvent(event); 拿到监听者的实例,直接调用 onApplicationEvent() 方法

为了揭秘上面两个问题,我们继续观察 AbstractApplicationContext 类,这个类里有我们想要的答案;

也就是说在容器启动过程中会装载ApplicationEventMulticaster,以及存放applicationListeners到容器中。

最后更新于

这有帮助吗?