Spring中的事件驱动模型(一)

2018-02-27 11:44:19来源:http://blueskykong.com/2018/02/22/spring-event-sourcing/作者:Aoho's Blog人点击

分享

事件驱动模型通常也被理解成观察者或者发布/订阅模型。


是一种对象间的一对多的关系;
当目标发送改变(发布),观察者(订阅者)就可以接收到改变;
观察者如何处理,目标无需干涉,它们之间的关系是松耦合的。


事件驱动模型的例子很多,如生活中的红绿灯,以及我们在微服务中用到的配置中心,当有配置提交时出发具体的应用实例更新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启动后触发的事件;


public abstract class ApplicationEventextends EventObject{
private static final long serialVersionUID = 7099057708183571937L;
//事件发生的时间
private final long timestamp = System.currentTimeMillis();
//创建一个新的ApplicationEvent事件
public ApplicationEvent(Object source){
super(source);
}
public final long getTimestamp(){
return this.timestamp;
}
}

事件基类 ApplicationEvent ,所有的具体事件都会继承该抽象事件类。


事件监听者

ApplicationListener 继承自JDK的 EventListener ,JDK要求所有监听器将继承它。


@FunctionalInterface
public interface ApplicationListener<Eextends ApplicationEvent>extends EventListener{
void onApplicationEvent(E var1);
}

提供了onApplicationEvent方法,用以处理 ApplicationEvent ,不过对于具体事件的处理需要进行判断。而 GenericApplicationListener 和 SmartApplicationListener 提供了关于事件更多的元数据信息。


public class SourceFilteringListenerimplements GenericApplicationListener,SmartApplicationListener{
private final Object source;
@Nullable
private GenericApplicationListener delegate;
//为特定事件源创建SourceFilteringListener,并传入代理的监听器类
public SourceFilteringListener(Object source, ApplicationListener<?> delegate){
this.source = source;
this.delegate = (delegate instanceof GenericApplicationListener ?
(GenericApplicationListener) delegate : new GenericApplicationListenerAdapter(delegate));
}
//....省略部分代码
@Override
public int getOrder(){
return (this.delegate != null ? this.delegate.getOrder() : Ordered.LOWEST_PRECEDENCE);
}
//过滤之后实际处理事件
protected void onApplicationEventInternal(ApplicationEvent event){
//...
this.delegate.onApplicationEvent(event);
}
}

SourceFilteringListener 是 ApplicationListener 的装饰器类,过滤特定的事件源。只会注入其事件对应的代理监听器,还提供了按照顺序触发监听器等功能。


在启动的时候会加载一部分 ApplicationListener 。Spring Context加载初始化完成(refresh)后会再次检测应用中的 ApplicationListener ,并且注册,此时会将我们实现的 ApplicationListener 就会加入到 SimpleApplicationEventMulticaster 维护的 Listener 集合中。


Spring也支持直接注解的形式进行事件监听 @EventListener(Event.class) 。


事件发布

ApplicationContext 接口继承了 ApplicationEventPublisher ,并在 AbstractApplicationContext 实现了具体代码,实际执行是委托给 ApplicationEventMulticaster 。


@FunctionalInterface
public interface ApplicationEventPublisher{
//通知所有的注册该事件的应用,事件可以是框架事件如RequestHandledEvent或者特定的应用事件。
default void publishEvent(ApplicationEvent event){
this.publishEvent((Object)event);
}
void publishEvent(Object var1);
}

实际的执行是委托给,读者有兴趣可以看一下 AbstractApplicationContext 中这部分的逻辑。下面我们具体看一下 ApplicationEventMulticaster 接口中定义的方法。


public interface ApplicationEventMulticaster{
//增加监听者
void addApplicationListener(ApplicationListener<?> listener);
//...
//移除监听者
void removeApplicationListener(ApplicationListener<?> listener);
//...
//广播特定事件给监听者
void multicastEvent(ApplicationEvent event, @Nullable ResolvableType eventType);
}

AbstractApplicationContext 中定义了对监听者的操作维护,如增加和删除,并提供了将特定事件进行广播的方法。下面看一下具体实现类 SimpleApplicationEventMulticaster 。 ApplicationContext 自动到本地容器里找一个 ApplicationEventMulticaster 实现,如果没有则会使用默认的 SimpleApplicationEventMulticaster 。


public class SimpleApplicationEventMulticasterextends AbstractApplicationEventMulticaster{
@Nullable
private Executor taskExecutor;
//...
//用给定的beanFactory创建SimpleApplicationEventMulticaster
public SimpleApplicationEventMulticaster(BeanFactory beanFactory){
setBeanFactory(beanFactory);
}
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType){
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
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);
}
...
}
else {
doInvokeListener(listener, event);
}
}
@SuppressWarnings({"unchecked", "rawtypes"})
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event){
try {
listener.onApplicationEvent(event);
}
//...
}
}

在 multicastEvent 方法中,executor不为空的情况下,可以看到是支持异步发布事件。发布事件时只需要调用 ApplicationContext 中的 publishEvent 方法即可进行事件的发布。


总结

本文主要介绍了Spring中的事件驱动模型相关概念。首先介绍事件驱动模型,也可以说是观察者模式,在我们的日常生活中和应用开发中有很多应用。随后重点篇幅介绍了Spring的事件机制,Spring的事件驱动模型由事件、发布者和订阅者三部分组成,结合Spring的源码分析了这三部分的定义与实现。笔者将会在下一篇文章,结合具体例子以及Spring Cloud Config中的实现进行实战讲解。


最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台