Spring Event事件驱动
简介
在一些应用场景中,我们希望程序是被“事件”触发运行的,并且程序在感知到不同的“事件”后能够产生不同的响应动作,此时就需要应用程序能够实时“感知”其所关心的事件,并在事件发生后执行相应的操作。总结:由事件驱动业务进行。
常用的设计模式:观察者模式、发布订阅模式。
使用场景
- 将不相干的业务解耦,比如完成业务操作后的短信通知之类的可以解耦的逻辑。
- 异步处理,在发布事件后,处理可以是异步完成,在有些耗时较长业务处理时,可以拆分逻辑,有些可以异步事件处理。
对比类似技术
-
MQ:消息队列是一种基于发布订阅模式的中间件。
-
优势:1.他能在不同系统中实现消息通讯;2.他有消息持久化机制,并且能够在大量消息处理时削峰。3.消息监控
-
劣势:1.单独的服务部署,需要资源。2.项目复杂化,增加网络通讯成本。
在合适的场景选择合适的技术。
-
-
异步线程池处理:使用异步线程处理也可解耦,并且出错不影响主业务执行
- 优势:编码简单、逻辑透明,也可解决处理耗时痛点。
- 劣势:逻辑并没有解耦,代码维护性降低,在新增处理逻辑时会有代码侵入。
Spring事件驱动模型
参考发布订阅模式或者观察者模式,实现事件驱动一般会有三个要素:事件源、各种类型监听器、发布者;一般来说发布者收到事件后,轮询应该处理的监听器,来执行业务处理操作。
事件
事件对接直接继承于Java原生的EventObject。
我们可以自定义ApplicationEvent对象的子类作为我们程序中的事件对象,也可以在传递事件时,直接使用我们的对象当构造参数实例化该对象。
发布器
这个我们可以自己实例化一个自己需要用的这个事件广播器,使用该对象广播事件。
注:在Spring的容器中,AbstractApplicationContext存在一个事件广播器(ApplicationEventMulticaster
),是用同一个还是自定义,这个根据实际情况使用。
事件监听器
实现ApplicationListener或者GenericApplicationListener(带泛型的事件监听)这两种接口,即可完成事件监听的处理方法。
关键部分代码
-
org.springframework.context.ApplicationListener
监听器接口
@FunctionalInterface public interface ApplicationListener<E extends ApplicationEvent> extends EventListener { /** * Handle an application event. * @param event the event to respond to */ void onApplicationEvent(E event); }
-
org.springframework.context.event.SimpleApplicationEventMulticaster
轮询监听器执行,这里可以使用异步线程池处理
@Override public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) { ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event)); Executor executor = getTaskExecutor(); for (ApplicationListener<?> listener : getApplicationListeners(event, type)) { if (executor != null) { executor.execute(() -> invokeListener(listener, event)); } else { invokeListener(listener, event); } } }