Hyperf 3.0 AOP切面失效主因是切面类未被扫描到,需确保scan.paths包含切面目录(如BASE_PATH . '/app/Aspect'),执行di:init-proxy生成缓存,并正确使用PHP 8 Attributes语法#[Aspect]。

切面类没被扫描到,注解压根没解析
Hyperf 3.0 的 AOP 依赖注解扫描生成代理类,不是“写了就生效”。#[Aspect] 类如果不在 scan.paths 配置范围内,框架连文件都不会读,更不会注册为切面 Bean。
- 检查
config/autoload/annotations.php中的scan.paths是否包含你的切面目录,比如BASE_PATH . '/app/Aspect'(注意不是app/Aspect) - Windows 用户务必用正斜杠,
appAspect是无效路径 - 自定义模块(如
MyAppAspect)需同步更新composer.json的autoload.psr-4和annotations.php - 执行
php bin/hyperf.php di:init-proxy—— 这不是可选步骤,是必须触发的扫描+缓存生成动作
SCAN_CACHEABLE=true 但缓存文件缺失
这个配置不是“自动缓存开关”,它只控制是否跳过扫描:只有当 runtime/container/annotation/ 下存在合法 PHP 缓存文件时,才会生效;否则静默跳过,切面不注册。
- 首次部署或修改
scan.paths后,必须手动运行php bin/hyperf.php di:init-proxy - Docker 构建时,确保
runtime/container/没被.dockerignore过滤,也不能在ENTRYPOINT里清空它 - 加密发布前,必须保留已生成的
runtime/container/annotation/*.php文件,删掉就等于关掉 AOP
PHP 8 Attributes 写法错误导致静默忽略
Hyperf 3.0 彻底弃用 Doctrine 风格注释(如 /** @Aspect */),也不识别属性类型提示。错一个字符,注解就等于不存在,且无任何报错日志。
- 必须用
#[Aspect],不能写成@Aspect或/* @Aspect */ - 切点表达式要用
#[Pointcut],参数必须是字符串字面量,如#[Pointcut("execution(* App\Service\*->*())")] - 通知方法签名要严格匹配,比如
#[Around]方法第一个参数必须是ProceedingJoinPoint类型 - 不要混用旧版
@Inject或@Value注解,Hyperf 3.0 只认 PHP 8 Attributes
切点表达式匹配失败,目标方法未被织入
即使切面类被成功加载,#[Pointcut] 表达式写错也会导致“看起来生效了,实际没拦截”。Hyperf 不像 Spring 那样打印代理创建日志,失效非常安静。
- 确认目标方法是
public,private/protected/static方法无法被拦截 - 包名和类名大小写必须完全一致,
AppServiceUserService≠AppServiceuserservice - 方法名后加
()表示无参,(..)表示任意参数,漏写会导致匹配失败 - 用
#[Pointcut("execution(* App\Service\UserService->getUser(..))")]而不是模糊的通配符
Hyperf 的 AOP 失效几乎总是发生在“扫描→解析→织入”链条的前端环节,而不是运行时逻辑问题。最常被忽略的是 di:init-proxy 没跑,以及 scan.paths 漏目录——这两点不解决,后面所有配置都白调。



















