事件系统与服务容器
理论突破,往往带来实践的创新。反之实践不甚其解,通常是没有掌握好理论。
Symfony
事件系统,涉及到派遣器(事件触发),订阅器(事件收集),事件对象(数据附加),监听器(事件执行),事件传播,事件队列优先级,以及程序组件间的通信
服务容器
每一个服务都被存放于一个特殊的名为
service container
(服务容器)之中 容器把对象的组织方式中心化
- 取得并使用服务
- 在控制器中借助“服务的类名或接口名”, 对
action
的参数进行type-hinting
以“请求”容器中的服务 - 可以使用唯一的 "Service ID" 来直接访问服务, 继承 Controller 类时内部可直接从容器中取出服务
- 在控制器中借助“服务的类名或接口名”, 对
事件派遣
Symfony
自身提供的内部事件,被定义在KernelEvents
类中 在sf
程序执行期间,大量的事件通知会被触发,程序可监听这些通知,并执行任意代码作为响应
- 事件监听器
- 通常由事件类和监听接口组成
- 接收事件对象参数,事件对象持有派遣器自身引用,该引用实例可决定事件能否继续传播
- 事件监听器优先级,Symfony的内部监听,其优先级范围是-255到255,默认值为0,顺序执行
- 监听器模式
- 监听者模式是基于:注册-回调的事件/消息通知处理模式,就是被监控者将消息通知给所有监控者
- 事件派遣器
- 事件触发调用者,事件源
- 事件类注册成服务,可命名
tags
- 一个单一的事件派遣器创建之后,它要维护全部相关监听器的“登记”
- 当事件通过
dispatcher
被派遣时,所有已注册的监听器会接到通知 - 内核通知
dispatcher
对象派遣事件,派遣器通知事件的全部监听器,监听器执行
- 事件订阅
- 订阅器始终明确知道正在监听的事件
- 定义了一个或多个方法,用于监听一个或多个事件
- 监听 VS 订阅
- 订阅器易于复用 与事件有关的内容存在于类中,而不是存在于服务定义中,故
sf
内部使用订阅器 - 监听器更灵活,因
bundles
可以有条件地开启或关闭它们,基于配置文件中的某些“选项值”
- 订阅器易于复用 与事件有关的内容存在于类中,而不是存在于服务定义中,故
EventDispatcher组件
- 作用 使组件之间“通过派遣事件和监听事件”进行互相通信
- 应用背景
- 需要在项目中提供一个插件系统
EventDispatcher
组件以一种简单高效的方式,实现了Mediator
设计模式- 中介者定义一个接口用于与各同事对象通信
- 每一个同事对象在需与其他同事通信时,与它的中介者通信
- 使控制集中化,减少了子类的生成,将各个同事类解耦,协议多向
- 可以使用
Observer
模式与Mediator
通信
- 事件
- 当一个事件被派遣时,该事件被多个监听器来监听。
- 一个Event实例将被同时创建,并被传递给所有的监听器
Event
对象自身往往包含着被派遣事件的数据
- 事件名称和事件对象
Event
类 默认包含一个用于停止event.propagation
方法- 特定事件的数据,则为一个拥有附加方法来取得或重写这些数据的特殊子类
- 连接到监听器
- 欲利用已有的事件,需要访问派遣器下的监听器
- 派遣器的
addListener()
方法被调用时,可以把任何一个有效的PHP回调(callable)关联到那个事件- 同
yii2
一样, 监听器addListener()方法有三个参数 - 事件名称(字符串),监听器需要监听到它
- 一个PHP回调,将在特定的事件被派遣时被执行
- 一个可选的整数优先级(愈高则愈重要,该监听将被愈早地触发)
- 同
- 一旦监听被注册到派遣器,它就等待着事件被通知(到自己)
- 在服务容器中注册事件监听
- 支持把事件派遣器注册成服务
- 支持把监听器注册成服务
- 支持把订阅器注册成服务
- 派遣Event
dispatch()
方法可以通知给定事件的全部监听- 要派遣的事件名称,以及用于传给每个监听的Event实例
- 事件派遣器永远返回被派遣的事件对象
- 使用事件订阅器
- 监听事件的常规方式就是去注册一个监听器给事件派遣器
- 或通过
event subscriber
(订阅器), 向派遣器精确通报它要订阅哪些事件- 除了它自己告诉派遣器“要监听哪些事件”之外,也需要将该订阅器注册给派遣器
- 停止Event Flow/Propagation
- 原因 在某些场合,一个监听在作动时,防止其他监听被调用是有意义
- 换言之,监听器必须能够告诉派遣器,停止向后续的监听进行关于此事件的全部传播
EventDispatcher Aware
的事件和监听EventDispatcher
始终向监听器传递被派遣的事件、事件名和一个对派遣器自身的引用
- 原因 在某些场合,一个监听在作动时,防止其他监听被调用是有意义
- 其他派遣器
The Container Aware Event Dispatcher
The Immutable Event Dispatcher
The Traceable Event Dispatcher(由HttpKernel组件提供)
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: