- 在设计模式中,观察者模式能够算得上是一种很是经典的行为设计模式,事件---事件发布者---事件监听者是事件驱动模型在设计层面的体现.
- 在
Spring
容器中经过ApplicationEvent
类和ApplicationListener
接口来处理事件的.若是某个bean
实现ApplicationListener
接口并被部署到容器中,那么每次对应的ApplicationEvent
被发布到容器中都会通知该bean
,这是典型的观察者模式.Spring
的事件默认是同步的,即调用#publishEvent
方法发布事件后,它会处于阻塞状态,直到#onApplicationEvent
接受到事件并处理返回以后才继续执行下去,这种单线程同步的好处是能够进行事务管理.- 系统默认提供的容器事件的异步发布机制参数
事件java
- 其继承自
JDK
的EventObject
,JDK
要求全部的事件都继承它,并经过#resource
获得事件源,咱们的AWT事件体系也是继承自它.- 系统默认提供以下
ApplicationEvent
事件:
目标(事件发布者)设计模式
- 具体表明:
ApplicationEventPublisher
和ApplicationEventMulticaster
,系统提供以下实现:
ApplicationContext
接口继承了ApplicationEventPublisher
,并在abstractApplicationContext#publishEvent
方法实现具体代码,实际执行委托给ApplicationEventMulticaster#multicastEvent
方法.ApplicationContext#initApplicationEventMulticaster
方法会自动到本地容器里找一个名为ApplicationEventMulticaster
的实现,若是没有就new
一个SimpleApplicationEventMulticaster
.- 能够看到若是提供一个
executor
,它就能够异步支持发布事件,不然为同步发布.
监听器异步
具体表明:
ApplicationListener
源码分析
- 其继承自
JDK
的EventListener
,JDK
要求全部的监听器将继承它,好比咱们的AWT
事件体系也是继承自它.ApplicationListener
接口:其只提供了#onApplicationEvent
方法,咱们须要在该方法实现内部判断事件类型来处理,若想提供顺序触发监听器的语义,则可使用另外一个接口:SmartApplicationListener
现假设一个用户注册的案例场景.用户注册后,系统须要给用户发送邮件告知用户注册是否成功,须要给用户初始化积分,后续可能会添加其余的操做,如再发一条手机短信等,但愿程序具备拓展性符合开闭原则.spa
- 若是不使用事件驱动,代码可能会像这个样子:
![]()
要说代码有什么问题其实也不算,由于大多数人在开发时第一直觉都会这么写,写同步代码.可是这么写,实际上并非特别符合隐含的设计需求,假设增长更多的注册项
Service
,咱们须要修改#register
方法,并让UserService
注入对应的Service
.而实际上register
并不关心这些"额外"的操做,如何将这些代码抽取出去,这时能够考虑Event
机制.线程
定义用户注册事件设计
ApplicationEvent
是由Spring
提供的全部Event
类的基类,这里为了简单只传递name
.
定义用户注册服务(事件发布者)3d
- 服务交给
Spring
容器管理.ApplicationEventPublishAware
是由Spring
提供的用于Service
注入ApplicationEventPublisher
事件发布器的接口.使用这个接口,咱们的Service
就拥有发布事件的能力了.- 用户注册后,再也不是显示调用其余的业务
Service
,而是发布一个用户注册事件
定义邮件服务,积分服务,其余服务(事件订阅者)code
- 事件订阅者的服务一样须要托管于
Spring
容器ApplicationListener<E extends ApplicationEvent>
接口是Spring
提供的事件订阅者必须实现的接口,咱们通常把Service
关心的事件做为泛型传入.- 事件处理:
ApplicationEvent#getSource
拿到事件的具体内容,本例中为name
.
- 当发布多个事件的时候,他们的顺序是无序的.若是要控制顺序,则监听器
Service
须要实现Order
接口或者使用SmartApplicationEventListener
.- 经过
Spring
事件驱动模型,咱们完成了注册服务和其余服务之间的解耦,这也是事件驱动的最大特性之一,若后续要新增其余操做,只须要添加相应的事件订阅者便可.
supportsEventType
:用于指定支持的事件类型,只有支持的才调用#onApplicationEvent
方法.supportsSourceType
:支持的目标类型,只有支持的才调用#onApplicationEvent
方法.getOrder
:顺序越小优先级越高,监听器默认优先级为7
.
- 注解式的事件发布者:
Spring4.2
以后,ApplicationEventPublisher
自动被注入到容器中,再也不须要显示实现Aware
接口
- 注解式的事件订阅者:
@EventListener
注解完成了ApplicationListener<E extends ApplicationEvent>
接口的使命.
java
配置经过@EnableAsync
模块注解开启异步支持,使用@Async
注解对须要异步的监听器进行标注.
- 事件(
ApplicationEvent
):继承JDK
的EventObject
在Spring
项目中能够继承ApplicationEvent
来定义本身的事件事件发布者(
Application
):实现这个接口,就可使得Spring
组件有发布事件的能力,ApplicationContext
实现了此接口,所以,发布事件的方式有以下几种:对象
- 经过实现
ApplicationEventPublisherAware
接口,获取注入的ApplicationPublisher
对象来进行事件发布.- 经过实现
ApplicationContextAware
接口,获取注入的ApplicationContext
来进行事件发布.- 经过
@autowired
注解直接注入ApplicationEventPublisher
或者ApplicationContext
对象来调用AbstractApplicationContext#publishEvent
来委托ApplicationEventMulticaster
进行事件发布
- 经过源码分析,在
AbstractApplicationContext
类中,定义了针对观察者的add,get,register
等方法,经过这一系列的方法向ApplicationEventMulticaster
类中维护listener
集合Set
.改Set
存储了该发布者全部的Listener
,因此ApplicationContext
容器会将注入到Spring
中的Listener
注册到ApplicationEventMulticaster
中
- 事件经过
AbstractApplicationContext#publishEvent
方法委托给AbstractApplicationEventMulticaster
进行事件发布,其中ApplicationEventMulticaster
会先尝试从ConfigurableListableBeanFactroy
中加载配置文件的类,若是不存在就会默认new
一个SimpleApplicationEventMulticaster
.
- 具体的事件发布会在
AbstractApplicaitonEventMulticaster#multicastEvent
中实现,实现流程为:先根据event
获取Listener
集合,在线程池不为空的状况下,异步发布特定类型的事件,不然同步发布.在#invokeListener
方法中最后调用Listener#onApplicationEvnet
方法实现了事件的发布.
- 以上就是关于
Spring
事件监听机制的分析,其本质上是观察者模式的实现.经过事件监听机制可以将咱们代码逻辑进行解耦,提升代码的拓展性,实现开闭原则.