priority 是解决 aop 切面执行顺序冲突的唯一可靠方式,因 hyperf 2.0 仅识别 public int $priority 属性,值越小优先级越高,且未声明或值相同时顺序不可控。

Hyperf 2.0 中 AOP 切面执行顺序不明确,会导致日志被重复记录、权限校验被跳过、事务未正确开启等实际问题——根本原因是多个切面匹配到同一目标方法时,框架默认不保证执行顺序,process 方法的调用次序由类加载顺序决定,不可控。
为什么 Priority 是解决冲突的唯一可靠方式
Hyperf 2.0 的 AOP 不支持 Spring 风格的 @Order 或 Ordered 接口,也不识别注解上的数字值;它只认切面类中显式声明的 public int $priority = 0; 属性。这个属性值越小,优先级越高(注意:不是越大越先执行),且仅在多个切面同时命中同一连接点时生效。
- 不声明
$priority→ 默认为0,所有未声明的切面视为同优先级,执行顺序不确定 - 两个切面都设
$priority = 10→ 仍不确定谁先执行,必须错开数值 - 优先级只影响环绕通知的
process方法嵌套顺序,不影响切面是否被加载
$priority 的典型取值策略与常见踩坑
不要用连续整数(如 1/2/3)或负数,避免后期插入新切面时频繁调整。推荐按语义分层设定:
- 底层基础设施类切面(如 DB 事务、连接池监控)→
$priority = -100 - 业务横切逻辑(如权限校验、参数验证)→
$priority = 0 - 观测类切面(如耗时统计、日志打点)→
$priority = 100 - 兜底/异常处理切面(如统一错误包装)→
$priority = 200
容易踩的坑:$priority 必须是 public 成员变量,且类型为 int;写成 protected、private 或字符串(如 "100")均无效,框架会静默忽略。
本页面提供企业级 PHP 协程框架 Hyperf 3.1.66 版本的官方源码下载与完整更新日志。重点解析 v3.1.66 版本中新增的 gRPC 多客户端负载均衡支持、Pool 连接池全量刷新、Guzzle 持久化 Cookie 以及数据库 JSON 包含键查询等核心优化特性。
验证 $priority 是否生效的实操方法
仅靠日志时间戳无法判断嵌套顺序,必须通过 ProceedingJoinPoint 的执行栈确认:
- 在每个切面的
process开头加一行:$this->logger->debug("[$priority] before {$proceedingJoinPoint->className}::{$proceedingJoinPoint->methodName}"); - 在
$proceedingJoinPoint->process()后加一行:$this->logger->debug("[$priority] after {$proceedingJoinPoint->className}::{$proceedingJoinPoint->methodName}"); - 观察 debug 日志输出顺序:高优先级(数值小)的
before一定最先出现,其after一定最后出现
如果发现两个 before 交替出现,说明 $priority 未被识别——立刻检查属性可见性、类型和拼写。
真正麻烦的不是设错 $priority,而是多个切面依赖同一个 Context 或 Coroutine\Channel 传递数据时,没意识到它们的嵌套深度已因优先级改变而错位。这种问题不会报错,只会让上下文值“莫名消失”或“被覆盖”。










