hyperf AOP切面
简单来说,AOP 让你能在不修改原有业务代码的情况下,为特定的类方法“统一添加”或“改变”一段通用逻辑,比如自动缓存、日志记录、事务管理等。它就像是一个“代码插件”系统,实现了核心业务与通用功能的完美解耦。
🎯 核心概念与 Hyperf 的实现方式
文档将 AOP 定义为通过动态代理等技术,在任意类的任意方法执行流程中“介入”,从而改变或加强原方法功能。这里有两个关键点:
-
切面 (Aspect):定义“在哪里”以及“做什么”的类。它指定要拦截的目标(类或注解),并包含增强处理的逻辑。
-
代理类 (ProxyClass):Hyperf 会为每个被切入的目标类动态生成一个代理类。当你调用目标方法时,实际上调用的是代理类的方法,它负责执行切面逻辑并决定如何调用原方法。
Hyperf 的特色在于,它简化了 AOP 的使用,只提供“环绕 (Around)”这一种通用模式。你只需在一个 process 方法中,就能完全控制目标方法调用前后的所有行为,灵活性极高。
🔧 如何定义和使用一个切面
文档提供了两种等价的定义方式,核心是以下三个部分:
1. 指定切入目标
通过 $classes(类/方法)和 $annotations(注解)数组来声明你要拦截什么。支持精确匹配和模糊匹配(使用 *)。
public array $classes = [
SomeService::class, // 切入该类的所有方法
'App\Service\SomeService::someMethod', // 切入特定方法
'App\Service\SomeService::*Method', // 切入以“Method”结尾的所有方法
];
public array $annotations = [
SomeAnnotation::class, // 切入所有使用该注解的类或方法
];
2. 编写增强逻辑
在 process(ProceedingJoinPoint $proceedingJoinPoint)`` 方法中实现你的核心逻辑。ProceedingJoinPoint对象是你控制流程的关键,通过它的process()` 方法来调用原方法。
public function process(ProceedingJoinPoint $proceedingJoinPoint)
{
// 1. 调用原方法之前的逻辑(例如:记录开始时间、检查权限)
$startTime = microtime(true);
// 2. 决定是否及如何调用原方法
$result = $proceedingJoinPoint->process(); // 这里会调用真实的目标方法
// 3. 调用原方法之后的逻辑(例如:记录耗时、处理结果、缓存)
$endTime = microtime(true);
$this->logger->info('方法执行耗时:' . ($endTime - $startTime));
return $result;
}
3. 让切面生效
有两种方式让框架识别你的切面类:
-
在类上使用
#[Aspect]注解(推荐)。 -
在
config/autoload/aspects.php配置文件中进行注册。两者效果相同。
⚙️ 在切面中能做什么
文档展示了 ProceedingJoinPoint 提供的强大能力,让你能在切面内获取丰富的上下文信息:
| 能力 | 方法示例 | 典型用途 |
|---|---|---|
| 获取方法反射与参数 | getReflectMethod(), getArguments() |
检查参数、基于参数生成缓存Key。 |
| 获取原实例 | getInstance() |
调用目标对象的其他方法。注意:这会返回代理类,要避免循环调用。 |
| 获取注解元数据 | getAnnotationMetadata() |
读取方法或类上的注解信息,实现高度动态的增强(如读取@Cacheable的TTL)。 |
| 控制原方法执行 | processOriginalMethod() |
调用不受其他切面影响的“最原始”方法。 |
| 完全取代原方法 | 不调用 process(),直接返回自定义结果 |
实现熔断、Mock数据或基于条件的短路返回。 |
💡 重要实践:代理类缓存
这是影响性能和部署的关键点。所有被切入的类都会在 `./runtime/container/proxy/`` 目录下生成代理类缓存文件。
-
开发环境:建议将 config/config.php 中的 scan_cacheable 设为 false(默认值)。这样每次启动都会重新扫描代码并生成代理类,方便调试,修改后重启即可生效。
-
生产环境:为了提升启动速度、降低内存占用,应该:
-
执行命令 php bin/hyperf.php 提前生成所有代理类。
-
将 scan_cacheable 配置设为 true。
-
在Docker镜像构建等部署环节,可将生成的代理类缓存直接打包进镜像,避免运行时再生成。
💎 总结
Hyperf 的 AOP 是一个强大的非侵入式增强工具。它将日志、缓存、事务等横切关注点从业务代码中剥离出来,使你的业务类保持纯净、职责单一。通过定义切面,你可以将这些通用功能像“乐高积木”一样灵活地组装到任何需要的地方。

浙公网安备 33010602011771号