Hyperf中$priority属性不生效,实际执行顺序由@Aspect注解的priority参数决定,而非类内$priority字段;同一方法匹配多个切面时,按priority数值从大到小排序,相同时回退至容器注册顺序。

Hyperf中$priority属性是否生效
不生效。Hyperf的Aspect类里定义$priority属性(比如protected $priority = 100;)**完全不会影响切面执行顺序**——框架根本不会读取这个字段。这是文档缺失和开发者误读源码导致的常见误解。
Hyperf切面实际执行顺序由什么决定
Hyperf使用AnnotationAspectContainer管理切面,最终排序依据是:切面类在容器中的注册顺序,也就是@Aspect注解被扫描到的先后顺序,而非类内属性。
- 同一文件中多个
@Aspect类:按代码从上到下顺序注册 - 不同文件:取决于Composer的自动加载顺序(通常是文件名字母序,但不可靠)
- 手动注册(如
Container::set()):按set调用顺序
如何可靠控制切面优先级
必须通过@Aspect注解的priority参数显式声明,且该值仅在当前切面作用域内参与排序(数值越大越先执行):
@Aspect(priority=200)
class LogAspect implements AspectInterface
{
// ...
}
注意以下关键点:
-
@Aspect(priority=...)是唯一有效方式,$priority属性会被忽略 - 优先级只影响同一切面匹配目标方法时的执行次序,不跨切面类型(如
Before和After仍按AOP生命周期固定顺序) - 若多个切面匹配同一方法,priority值相同时,注册顺序回退为最终决定因素
- Hyperf 3.x 中priority支持浮点数(如
100.5),可更精细控制
调试切面执行顺序的方法
当行为不符合预期时,不要猜,直接看框架实际加载结果:
- 启用调试模式后,在
var/log/hyperf.log中搜索"Loaded aspect",日志会按注册顺序打印所有切面类及priority值 - 在
AspectManager中打断点,检查$this->aspects数组内容(key为priority,value为切面实例数组) - 避免在
before中修改上下文后,期望after能感知——它们属于不同切面实例,无共享状态
真正难的不是设优先级,而是理解Hyperf把“切面注册”和“切面逻辑执行”分成了两个阶段,而文档没说清这个分离设计。


















