一、 背景
在软件开发过程中,同事在迁移代码的过程中,对于项目中实现的数据变更一致性问题的实现提出了问题,首先了解一下数据变更一致性问题,比如监控点资源、组织资源、人员资源等变更,那么就要通知其他涉及到改数据的模块,进行相应的数据变更,使得数据保持一致性。在现有的项目中通常涉及其他组件的通知变更都是通过MQ接收消息,然后将消息转发到相关的模块进行业务逻辑的修改。同事提出的问题?原由在接收到MQ消息之后通知的实现上,具体如下图 所示
其实现思路为通过一个线程不断的轮询LinkedBlockingQueue,然后在通过获取队列中的信息的类型、执行动作等在调用相关的模块的逻辑实现。同事提出的问题是:为什么需要单独的实现一个线程去处理,不断的轮询浪费资源。确实是浪费资源,因为本人提出了自己的实现的思路,并给予讲解,因此总结一下。由于当前的背景本身就是一个非常典型的消息通知机制,这种本地化的消息通知机制,使用spring提供的消息驱动模型很好的解决问题,spring事件本来就是为了解决这类的问题而产生的。
二、 Spring 事件机制介绍
Spring事件机制的介绍分为三个模块进行讲解,如下图所示:
1、 事件驱动
从程序设计的角度来看,事件驱动模型的核心构件通常包含(事件源:负责产生事件的对象; 事件监听器:负责处理事件的对象; 事件:或者称为事件对象,是事件源和事件监听器之间的信息桥梁。是整个事件模型驱动的核心),下图为三者之间的关系
程序中常见的事件驱动概念,从观察者模式、发布订阅模式、消息中间件、已经spring等对于事件机制的支持。
2、 Spring事件支持
Spring对于事件机制的支持对应消息驱动模型中的监听器、事件源、事件等概念
1) ApplicationListener监听器
监听器接口如下:
监听器职责:
2) ApplicationEventPublisher事件源
接口图:从图中可以看出实现了发送事件、或者发送包装事件原理
接口继承图:从继承图中可以看出,对于事件源的发送可以通过ApplicationContext Bean工厂进行发送处理事件消息。
职责:
3) ApplicationEvent 事件
抽象类实现图:从实现上看没有什么,仅仅是一个表征事件类型和携带事件信息的基类
职责:
4) ApplicationEventMulticaster 事件广播器
广播器也就是事件模型中的事件收集器,总是需要一个人来维护发送者和接受者之间的关系,广播器就是维护这样的角色的。
继承图:从继承图中可以粗略的了解广播器的角色,除了基本的监听器集合的维护之外还提供了一些同步异步处理等功能
职责:
3、 spring 处理流程
Spring处理流程最主要的就是维护广播器和监听器信息,通过将所有的监听者添加到广播器监听者集合中,事件源发送事件的时候,广播器能够找到将匹配到的事件的类型的所有监听者,然后通过同步或者异步的方式发送消息。
具体流程:
三、 项目中应用与改进
将背景中介绍的编码方式通过spring事件进行重写、能够很好的解耦、代码也更加的容易被理解。
1. 配置异步广播器
spring处理流程中提到,如果自己配置广播器,并配置线程线程池资源,可以异步的发送消息
实现逻辑图:
2. 自定义一个事件类型
在基本上不变化原有逻辑的基本上进行更改,实现一个事件类型
3. 事件源
实现发送事件思路挺多的,从介绍spring的事件源的继承图就可以了解到。通过获取Bean实例进行发送消息
下面列举几个:
A. 注入ApplicationEventPublisher applicationEventPublisher;
B. 注入ApplicationContext applicationContext
C. 实现ApplicationEventPublisherAware接口
D. 实现ApplicationEventPublisherAware接口
4. 监听器
实现自定义事件的监听、资源的各种变更是当前类似的事件即可处理业务逻辑。如下图所示
四、 总结
Spring事件驱动模型对于原有的实现进行改进,带有设计模式中观察者模式的味道、事件驱动的味道更加的利于程序员的理解代码的逻辑、业务的扩展性也比较强、如果增加新的业务直接注册自己需要监听的事件的类型不用修改原有的代码,满足开闭原则,一个软件实体如类、模版和函数应该对扩展,对修改关闭。
五、 参考资料
浅析 Spring 中的事件驱动机制
深入分析Spring事件驱动模型
spring事件驱动模型–观察者模式在spring中的应用
代码设计 六大原则