【hyperf 源码分析】AOP - (sunznx) 振翅飞翔
16 March 2020

在 java spring 中实现 AOP 是通过重写 java class 的字节码来实现的,我之前想过能不能修改 zend vm 来实现。
看了 hyperf 的实现之后,觉得这个实现也挺巧妙的,hyperf 是通过改写 php 代码文件来实现的。

所谓的 AOP 就是修饰器设计模式的一种?我一直理解是一个修饰器

假设 IndexControllerAspect

/**
 * @Aspect()
 */
class IndexConntrollerAspect extends AbstractAspect
{
    public $classes = [
        IndexController::class,
    ];

    public function process(ProceedingJoinPoint $proceedingJoinPoint)
    {
        $result = $proceedingJoinPoint->process();
        return "before {$result} after";
    }
}

因为 hyperf 在启动的时候会扫描注解, Aspect 是一个特殊的注解,hyperf 会收集该类的 classesannotations 属性。

  1. hyperf 的容器在实例化 IndexController::class 的时候会先去判断下,有没有对应的 Aspect
    判断的代码在 /hyperf/di/src/Definition/DefinitionSource.phpisNeedProxy 方法
    • 首先会根据前面收集到的 classes 判断 IndexController::class 在不在,如果在就说明需要 proxy 了
    • 如果 classes 判断失败了,那么算出 IndexControllerIndexController 下面所有方法使用到的 annotation ,如果这些 annotation 和上面收集到的 annotations 匹配到了,就说明需要 proxy 了
  2. 如果有对应的 Aspect 类,就不生成 IndexController 了,而是生成一个 IndexControllerProxy ,这个类是根据 IndexConntrollerAspect 动态生成。然后重写了对应的方法
    生成 proxy 类的代码在 /hyperf/di/src/Aop/Ast.phpproxy 方法里面