Spring中的事件驱动模型(一)
事件驱动模型
事件驱动模型通常也被理解成观察者或者发布/订阅模型。
- 是一种对象间的一对多的关系;
- 当目标发送改变(发布),观察者(订阅者)就可以接收到改变;
- 观察者如何处理,目标无需干涉,它们之间的关系是松耦合的。
event-source
事件驱动模型的例子很多,如生活中的红绿灯,以及我们在微服务中用到的配置中心,当有配置提交时出发具体的应用实例更新Spring上下文环境。
Spring的事件机制
基本概念
Spring的事件驱动模型由三部分组成:
- 事件:ApplicationEvent,继承自JDK的EventObject,所有事件将继承它,并通过source得到事件源。
- 事件发布者:ApplicationEventPublisher及ApplicationEventMulticaster接口,使用这个接口,我们的Service就拥有了发布事件的能力。
- 事件订阅者:ApplicationListener,继承自JDK的EventListener,所有监听器将继承它。
Spring事件驱动过程
事件
Spring 默认对 ApplicationEvent 事件提供了如下实现:
- ContextStoppedEvent:ApplicationContext停止后触发的事件;
- ContextRefreshedEvent:ApplicationContext初始化或刷新完成后触发的事件;
- ContextClosedEvent:ApplicationContext关闭后触发的事件。如web容器关闭时自动会触发Spring容器的关闭,如果是普通java应用,需要调用
ctx.registerShutdownHook()
注册虚拟机关闭时的钩子才行; - ContextStartedEvent:ApplicationContext启动后触发的事件;
eventobject
1public abstract class ApplicationEvent extends EventObject {
2 private static final long serialVersionUID = 7099057708183571937L;
3 //事件发生的时间
4 private final long timestamp = System.currentTimeMillis();
5 //创建一个新的ApplicationEvent事件
6 public ApplicationEvent(Object source) {
7 super(source);
8 }
9
10 public final long getTimestamp() {
11 return this.timestamp;
12 }
13}
事件基类ApplicationEvent
,所有的具体事件都会继承该抽象事件类。
事件监听者
ApplicationListener
ApplicationListener
继承自JDK的EventListener
,JDK要求所有监听器将继承它。
1@FunctionalInterface
2public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
3 void onApplicationEvent(E var1);
4}
提供了onApplicationEvent方法,用以处理ApplicationEvent
,不过对于具体事件的处理需要进行判断。而GenericApplicationListener
和SmartApplicationListener
提供了关于事件更多的元数据信息。
1public class SourceFilteringListener implements GenericApplicationListener, SmartApplicationListener {
2
3 private final Object source;
4
5 @Nullable
6 private GenericApplicationListener delegate;
7
8 //为特定事件源创建SourceFilteringListener,并传入代理的监听器类
9 public SourceFilteringListener(Object source, ApplicationListener<?> delegate) {
10 this.source = source;
11 this.delegate = (delegate instanceof GenericApplicationListener ?
12 (GenericApplicationListener) delegate : new GenericApplicationListenerAdapter(delegate));
13 }
14 //....省略部分代码
15
16 @Override
17 public int getOrder() {
18 return (this.delegate != null ? this.delegate.getOrder() : Ordered.LOWEST_PRECEDENCE);
19 }
20
21 //过滤之后实际处理事件
22 protected void onApplicationEventInternal(ApplicationEvent event) {
23 //...
24 this.delegate.onApplicationEvent(event);
25 }
26
27}
SourceFilteringListener
是ApplicationListener
的装饰器类,过滤特定的事件源。只会注入其事件对应的代理监听器,还提供了按照顺序触发监听器等功能。
在启动的时候会加载一部分 ApplicationListener
。Spring Context加载初始化完成(refresh)后会再次检测应用中的 ApplicationListener
,并且注册,此时会将我们实现的 ApplicationListener
就会加入到 SimpleApplicationEventMulticaster
维护的 Listener 集合中。
Spring也支持直接注解的形式进行事件监听@EventListener(Event.class)
。
事件发布
EventPublisher
ApplicationContext
接口继承了ApplicationEventPublisher
,并在AbstractApplicationContext
实现了具体代码,实际执行是委托给ApplicationEventMulticaster
。
1@FunctionalInterface
2public interface ApplicationEventPublisher {
3 //通知所有的注册该事件的应用,事件可以是框架事件如RequestHandledEvent或者特定的应用事件。
4 default void publishEvent(ApplicationEvent event) {
5 this.publishEvent((Object)event);
6 }
7
8 void publishEvent(Object var1);
9}
实际的执行是委托给,读者有兴趣可以看一下AbstractApplicationContext
中这部分的逻辑。下面我们具体看一下ApplicationEventMulticaster
接口中定义的方法。
1public interface ApplicationEventMulticaster {
2
3 //增加监听者
4 void addApplicationListener(ApplicationListener<?> listener);
5 //...
6
7 //移除监听者
8 void removeApplicationListener(ApplicationListener<?> listener);
9 //...
10
11 //广播特定事件给监听者
12 void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType);
13
14}
AbstractApplicationContext
中定义了对监听者的操作维护,如增加和删除,并提供了将特定事件进行广播的方法。下面看一下具体实现类SimpleApplicationEventMulticaster
。ApplicationContext
自动到本地容器里找一个ApplicationEventMulticaster
实现,如果没有则会使用默认的SimpleApplicationEventMulticaster
。
1public class SimpleApplicationEventMulticaster extends AbstractApplicationEventMulticaster {
2
3 @Nullable
4 private Executor taskExecutor;
5
6 //...
7
8 //用给定的beanFactory创建SimpleApplicationEventMulticaster
9 public SimpleApplicationEventMulticaster(BeanFactory beanFactory) {
10 setBeanFactory(beanFactory);
11 }
12
13 @Override
14 public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
15 ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
16 for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
17 Executor executor = getTaskExecutor();
18 if (executor != null) {
19 executor.execute(() -> invokeListener(listener, event));
20 }
21 else {
22 invokeListener(listener, event);
23 }
24 }
25 }
26
27 //注入给定事件的给定监听器
28 protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
29 ErrorHandler errorHandler = getErrorHandler();
30 if (errorHandler != null) {
31 try {
32 doInvokeListener(listener, event);
33 }
34 ...
35 }
36 else {
37 doInvokeListener(listener, event);
38 }
39 }
40
41 @SuppressWarnings({"unchecked", "rawtypes"})
42 private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
43 try {
44 listener.onApplicationEvent(event);
45 }
46 //...
47 }
48
49}
在multicastEvent
方法中,executor不为空的情况下,可以看到是支持异步发布事件。发布事件时只需要调用ApplicationContext
中的publishEvent
方法即可进行事件的发布。
总结
本文主要介绍了Spring中的事件驱动模型相关概念。首先介绍事件驱动模型,也可以说是观察者模式,在我们的日常生活中和应用开发中有很多应用。随后重点篇幅介绍了Spring的事件机制,Spring的事件驱动模型由事件、发布者和订阅者三部分组成,结合Spring的源码分析了这三部分的定义与实现。笔者将会在下一篇文章,结合具体例子以及Spring Cloud Config中的实现进行实战讲解。
参考
- 事件驱动模型简介
- Spring事件驱动模型与观察者模式
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- pytest 测试框架学习(10):pytest.param
- pytest 测试框架学习(11):pytest.raises
- Hibernate第二天:Hibernate的一级缓存、其他的API
- pytest 测试框架学习(12):pytest.deprecated_call
- Pinstaller(Python打包为exe文件
- pytest 测试框架学习(14):pytest.warns
- ImportError: /lib64/libm.so.6: version `CXXAB_1.3.8.' not found (required by /usr/local/python37/lib
- pytest 测试框架学习(15):pytest.freeze_includes
- Linux: scp文件,目录上传下载标准版
- Hibernate第三天:Hibernate的一对多配置、Hibernate的多对多的配置
- Git: 掉坑记 -- git reset 杀手
- ModuleNotFoundError: No module named 'phkit.pinyin'
- Hibernate第四天:Hibernate的查询方式、抓取策略
- 爬虫抓取博客园前10页标题带有Python关键字(不区分大小写)的文章
- Python爬虫抓取唐诗宋词