
后端Web框架微服务RPC框架异步编程【免费下载链接】hyperf A coroutine framework that focuses on hyperspeed and flexibility. Building microservice or middleware with ease.项目地址https://gitcode.com/hyperf/hyperf点击查看免费下载Hyperf 的事件机制基于 PSR-14 标准实现通过将事件触发方业务代码与事件处理方监听器彻底解耦让注册用户成功后的发邮件、发短信等旁路逻辑不再侵入核心业务方法。阅读本文后你将掌握在 Hyperf 中定义事件、编写并注册监听器配置文件与#[Listener]注解两种方式、按优先级触发事件的全过程并理解框架内置生命周期事件的运行时机与协程环境下的注入注意事项。事件机制概述为解耦而生事件模式Event Pattern是一种经过充分验证的可靠机制非常适合用于系统解耦。Hyperf 的事件模式实现遵循 PSR-14PHP 标准建议中关于事件分发器的规范默认由hyperf/event组件提供实现。该组件本身并不依赖 Hyperf 框架的其他部分同样可以被引入到其他框架或应用中独立使用。事件模式中存在三个核心角色Event事件在应用代码与Listener之间传递的通信对象通常是一个承载业务状态数据的普通类Listener监听器监听特定Event的发生并在事件被触发时执行相应处理逻辑Event Dispatcher事件分发器用于触发Event并管理Listener与Event之间关系的管理对象。用一个通俗的例子来说明假设我们有一个UserService::register()方法用于注册账号。账号注册成功后我们可以通过事件分发器触发UserRegistered事件监听器监听到该事件的发生后执行一些操作例如发送一条用户注册成功的通知。如果之后我们还想在用户注册成功后做更多事情比如发送一封注册成功邮件只需要再添加一个监听UserRegistered事件的监听器即可无需在UserService::register()方法中堆砌与注册逻辑无关的代码。这就是事件机制的核心价值业务主流程保持纯净扩展行为通过监听器增量叠加。安装 hyperf/event 组件在 Hyperf 项目中事件组件通常已经随框架默认引入若需要在其他框架或独立应用中单独使用通过 Composer 引入即可composer require hyperf/event组件安装后ConfigProvider见 src/event/src/ConfigProvider.php会自动完成核心依赖的绑定ListenerProviderInterface绑定到ListenerProviderFactoryEventDispatcherInterface绑定到EventDispatcherFactory从而在容器中就绪可用。定义事件一个承载数据的普通类事件本质上就是一个用于管理状态数据的普通类。触发事件时应用数据会被传递给事件对象随后由监听器对该事件对象进行操作。一个事件可以被多个监听器同时监听。?php namespace App\Event; class UserRegistered { // 建议定义为 public 属性监听器可直接使用也可以为该属性提供 Getter public $user; public function __construct($user) { $this-user $user; } }定义监听器实现 ListenerInterface监听器需要实现Hyperf\Event\Contract\ListenerInterface接口接口定义见 src/event/src/Contract/ListenerInterface.php该接口约束了两个方法listen(): array返回该监听器要监听的事件类名数组可同时监听多个事件process(object $event): void事件触发后监听器要执行的代码所有监听器的process都会在事件返回给EventDispatcher之前执行完毕。示例代码如下?php namespace App\Listener; use App\Event\UserRegistered; use Hyperf\Event\Contract\ListenerInterface; class UserRegisteredListener implements ListenerInterface { public function listen(): array { // 返回该监听器要监听的事件数组可同时监听多个事件 return [ UserRegistered::class, ]; } /** * param UserRegistered $event */ public function process(object $event): void { // 事件触发后监听器要执行的代码写在这里例如本例中的发送用户注册成功通知等 // 直接访问 $event 的 user 属性即可获取事件触发时传入的参数值 // $event-user; } }通过配置文件注册监听器定义好监听器后需要让Dispatcher能够发现它。可以在config/autoload/listeners.php配置文件中添加该文件不存在时可直接创建。监听器的触发顺序取决于配置文件中的配置顺序?php return [ \App\Listener\UserRegisteredListener::class, ];从源码看配置文件还支持键值对形式指定优先级。在 ListenerProviderFactory.php 的registerConfig方法中配置项被逐一解析当配置项为纯字符串整型下标时使用默认优先级ListenerData::DEFAULT_PRIORITY其值为0见 ListenerData.php当配置以监听器类名 优先级的键值对形式给出时则会使用指定的优先级注册?php return [ // 纯类名注册使用默认优先级 0 \App\Listener\UserRegisteredListener::class, // 键值对形式为该监听器指定优先级 \App\Listener\AnotherListener::class 10, ];通过注解注册监听器Hyperf 还提供了更便捷的注册方式使用#[Listener]注解。只要在监听器类上定义该注解监听器类便会被自动注册进 Hyperf 的注解扫描域无需手动写入配置文件。代码示例如下?php namespace App\Listener; use App\Event\UserRegistered; use Hyperf\Event\Annotation\Listener; use Hyperf\Event\Contract\ListenerInterface; #[Listener] class UserRegisteredListener implements ListenerInterface { public function listen(): array { // 返回该监听器要监听的事件数组可同时监听多个事件 return [ UserRegistered::class, ]; } /** * param UserRegistered $event */ public function process(object $event): void { // 事件触发后监听器要执行的代码写在这里 // $event-user; } }通过注解注册监听器时可以通过设置priority属性来定义当前监听器的执行顺序例如#[Listener(priority: 1)]。底层使用SplPriorityQueue结构存储监听器priority 数值越大优先级越高。对应的注解类定义见 src/event/src/Annotation/Listener.php其构造函数接收int $priority ListenerData::DEFAULT_PRIORITY作为唯一参数。使用#[Listener]注解时需要use Hyperf\Event\Annotation\Listener;引入对应命名空间。优先级机制同样有测试用例背书EventDispatcherTest.php 中的testListenersWithPriority以1、3、2、0、99、-99六个优先级注册监听器最终断言执行结果为[5, 2, 3, 1, 4, 6]即严格按数值从大到小99 3 2 1 0 -99的顺序触发验证了SplPriorityQueue的排序行为。触发事件通过 EventDispatcher 分发事件需要通过EventDispatcher分发后Listener才能监听到。下面用一段代码演示如何触发事件?php namespace App\Service; use Hyperf\Di\Annotation\Inject; use Psr\EventDispatcher\EventDispatcherInterface; use App\Event\UserRegistered; class UserService { #[Inject] private EventDispatcherInterface $eventDispatcher; public function register() { // 假设这里存在一个 User 实体 $user new User(); $result $user-save(); // 完成账号注册逻辑 // 这里的 dispatch(object $event) 会逐个执行监听器 $this-eventDispatcher-dispatch(new UserRegistered($user)); return $result; } }注意这里注入的是 PSR 标准的Psr\EventDispatcher\EventDispatcherInterface接口而不是具体实现类Hyperf 容器会自动将其解析为Hyperf\Event\EventDispatcher实例由 EventDispatcherFactory.php 创建。源码级原理分发与注册的完整链路分发器如何工作Hyperf\Event\EventDispatcher::dispatch()见 src/event/src/EventDispatcher.php的实现非常精简遍历ListenerProvider返回的监听器集合逐一以事件对象为参数调用监听器然后检查事件是否实现了Psr\EventDispatcher\StoppableEventInterface且已停止传播——若是则中断后续监听器执行否则继续最后将事件对象返回。此外若构造时传入了LoggerInterface每次分发都会输出一条 debug 日志记录事件类名与处理它的监听器类名便于排查问题。监听器提供器与优先级队列Hyperf\Event\ListenerProvider见 src/event/src/ListenerProvider.php负责按事件类型筛选监听器内部维护一个ListenerData数组记录事件、可调用监听器与优先级getListenersForEvent()通过$event instanceof $listener-event判断事件匹配关系并将命中的监听器按优先级插入Hyperf\Stdlib\SplPriorityQueue。对于非匿名类事件队列结果会被缓存复用避免重复构建。注册流程的统一入口无论是配置文件还是注解注册最终都汇聚到 ListenerProviderFactory.php 的register()方法先从容器中取出监听器实例若实现了ListenerInterface则遍历其listen()返回的事件列表调用$provider-on($event, [$instance, process], $priority)完成注册。注解注册则依赖AnnotationCollector扫描#[Listener]注解收集到的类信息对应源码registerAnnotations方法。提前终止事件传播对于需要某个监听器处理后不再继续的场景可让事件类实现Psr\EventDispatcher\StoppableEventInterface。Hyperf 为此提供了现成的Hyperf\Event\Stoppabletrait见 src/event/src/Stoppable.php内含$propagation状态、isPropagationStopped()与setPropagation(bool)方法事件内通过setPropagation(true)即可停止后续监听器执行。这一行为同样有测试覆盖testStoppable见 EventDispatcherTest.php验证了传播停止后后注册的监听器不再被执行。Hyperf 生命周期事件Hyperf 框架将 Swoole/Swow 服务启动、运行、停止过程中的关键节点以事件形式暴露便于开发者通过监听器在这些节点注入自定义逻辑。下图为 Hyperf 生命周期事件的完整时序从图中可以看到生命周期事件分布在Process自定义进程、Manager、Worker、Master、Command五个层面。结合 src/framework/src/Event/ 目录下的事件类可确认以下内置事件应用启动阶段BootApplication、BeforeMainServerStart、BeforeServerStartWorker 进程阶段BeforeWorkerStart、MainWorkerStart、OtherWorkerStart、AfterWorkerStart、OnWorkerExit、OnWorkerStop、OnWorkerErrorManager 进程阶段OnManagerStart、OnManagerStopMaster 进程阶段OnStart、OnShutdown网络事件OnPipeMessage管道消息、OnReceive、OnConnect、OnClose、OnPacket、OnTask、OnFinish。需要注意的是图中标注了Some events are not enabled by default部分事件默认未启用例如OnReceive、OnTask、OnFinish等依赖于服务类型与配置的回调事件需按需开启同时图中绿色框代表coroutine API safe协程 API 安全即在该事件回调内可以安全地使用协程相关 API。Hyperf 协程风格服务器的生命周期事件当使用 Hyperf 的协程风格服务器Coroutine Style Server对应Hyperf\Server\CoroutineServer见 src/server/src/CoroutineServer.php时事件时序与常驻 Swoole 服务不同Hyperf 为此提供了独立的协程服务器生命周期事件其事件类位于 src/server/src/Event/ 目录CoroutineServerStart协程服务器启动时触发CoroutineServerStop协程服务器停止时触发MainCoroutineServerStart主协程服务器启动时触发AllCoroutineServersClosed所有协程服务器关闭时触发。在协程风格下服务以协程而非进程/线程模型运行这些事件为开发者提供了与常驻服务OnStart、OnShutdown等相对应的挂载点。使用注意事项不要在 Listener 中注入 EventDispatcherInterfaceEventDispatcherInterface依赖ListenerProviderInterface而ListenerProviderInterface在初始化时会收集所有Listener。如果Listener又反过来依赖EventDispatcherInterface就会形成循环依赖最终导致内存溢出。最好只在 Listener 中注入 ContainerInterface建议在Listener中只注入ContainerInterface其余组件在process方法中通过容器按需获取。原因在于框架启动时EventDispatcherInterface会被实例化此时并非协程环境如果Listener注入了可能触发协程切换的类例如数据库连接、Redis 连接等会导致框架启动失败。将组件获取推迟到process执行阶段即可确保依赖解析发生在协程环境中规避该风险。?php namespace App\Listener; use Hyperf\Event\Contract\ListenerInterface; use Psr\Container\ContainerInterface; class DemoListener implements ListenerInterface { public function __construct(protected ContainerInterface $container) { } public function listen(): array { return [ DemoEvent::class, ]; } public function process(object $event): void { // 在 process 内通过容器获取可能触发协程切换的组件 $redis $this-container-get(\Hyperf\Redis\Redis::class); // ... 业务处理 } }小结Hyperf 的事件机制以 PSR-14 为规范通过Event、Listener、Event Dispatcher三角色实现业务解耦事件类承载数据监听器声明关注的事件并处理逻辑分发器负责按优先级调度。监听器既可通过config/autoload/listeners.php配置文件注册也可用#[Listener]注解注册并指定priority控制顺序分发过程支持StoppableEventInterface提前终止传播。在此基础上框架内置了覆盖服务全生命周期的框架级事件与协程风格服务器事件理解这些事件的触发时机并遵循Listener 只注入容器的规范即可安全地在 Hyperf 中构建高内聚、低耦合的扩展逻辑。赞分享后端Web框架微服务RPC框架异步编程【免费下载链接】hyperf A coroutine framework that focuses on hyperspeed and flexibility. Building microservice or middleware with ease.项目地址https://gitcode.com/hyperf/hyperf点击查看免费下载相关推荐Reflex 事件触发器Event Triggers完全指南从生命周期事件到全局键盘监听Reflex 事件触发器Event Triggers完全指南从生命周期事件到全局键盘监听 事件触发器Event Triggers是 Reflex 中连后端前端Web框架TEngine 事件系统GameEvent实战指南int/string 事件、UI 事件注册与全局生命周期管理TEngine 事件系统GameEvent实战指南int/string 事件、UI 事件注册与全局生命周期管理 本篇指南围绕 TEngine 框架的事件系游戏开发OpenHarmony-TPC/ImageKnife回调机制完整生命周期事件监听OpenHarmony TPC/ImageKnife回调机制完整生命周期事件监听 引言 在OpenHarmony应用开发中图像加载是高频且关键的操作。传统的OpenHarmony移动开发缓存上一篇gstack 设计教义理解用户真实行为为 AI 设计评审与方案生成注入可用性方法论下一篇DDD Guestbook数据访问层实现EF Core与仓储模式实战指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考