kode/aop 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

kode/aop

Composer 安装命令:

composer require kode/aop

包简介

基于 PHP 8.1+ 原生属性(Attribute)实现的轻量级、高性能、高扩展性 AOP(面向切面编程)组件

README 文档

README

PHP Version License

基于 PHP 8.1+ 原生属性(Attribute)实现的轻量级、高性能、高扩展性 AOP(面向切面编程)组件。

✨ 特性

  • 原生支持:基于 PHP 8.1+ 原生属性(Attribute)实现,IDE 友好
  • 轻量级:依赖 kode/attributes 包,无其他框架依赖
  • 高性能:使用缓存机制避免重复反射操作
  • 类型安全:充分利用 PHP 8.1+ 的类型系统,支持 readonly 属性
  • 扩展性强:支持前置通知(Before)、后置通知(After)、环绕通知(Around)
  • 优先级控制:支持通过 #[Priority] 注解控制切面执行顺序
  • 切入点表达式:支持通配符匹配,灵活定义切入点

📦 安装

composer require kode/aop

🚀 快速开始

1. 创建切面类

<?php

use Kode\Aop\Attribute\Aspect;
use Kode\Aop\Attribute\Before;
use Kode\Aop\Attribute\After;
use Kode\Aop\Attribute\Around;
use Kode\Aop\Runtime\JoinPoint;
use Kode\Aop\Runtime\ProceedingJoinPoint;

#[Aspect]
class LoggingAspect
{
    #[Before("execution(* App\Service\UserService->createUser(..))")]
    public function logBefore(JoinPoint $joinPoint): void
    {
        $args = $joinPoint->getArguments();
        echo "准备创建用户: " . json_encode($args[0]) . "\n";
    }

    #[After("execution(* App\Service\UserService->createUser(..))")]
    public function logAfter(JoinPoint $joinPoint): void
    {
        echo "用户创建操作已完成\n";
    }
}

2. 配置 AOP 内核

<?php

use Kode\Aop\Runtime\AspectKernel;

$kernel = AspectKernel::getInstance();
$kernel->registerAspect(new LoggingAspect());
$kernel->init();

$userService = $kernel->getProxy(UserService::class);

3. 使用代理对象

<?php

$result = $userService->createUser([
    'name' => 'John Doe',
    'email' => 'john@example.com'
]);

📖 详细文档

通知类型

Before(前置通知)

在目标方法执行前执行,可以修改方法参数或执行预处理逻辑。

#[Before("execution(* App\Service\*->*(..))")]
public function logBefore(JoinPoint $joinPoint): void
{
    $methodName = $joinPoint->getMethodName();
    $args = $joinPoint->getArguments();

    echo "方法 {$methodName} 即将执行\n";

    // 修改参数
    if (isset($args[0])) {
        $args[0] = trim($args[0]);
        $joinPoint->setArguments($args);
    }
}

After(后置通知)

在目标方法执行后执行(无论是否抛出异常),适用于资源清理、日志记录等场景。

#[After("execution(* App\Service\*->*(..))")]
public function logAfter(JoinPoint $joinPoint): void
{
    $result = $joinPoint->getResult();
    echo "方法执行完成,返回值: " . json_encode($result) . "\n";
}

Around(环绕通知)

环绕目标方法执行,可以完全控制方法的执行流程。

#[Around("execution(* App\Service\UserService->*(..))")]
public function transactional(ProceedingJoinPoint $joinPoint): mixed
{
    echo "开始事务\n";

    try {
        $result = $joinPoint->proceed();
        echo "提交事务\n";
        return $result;
    } catch (\Exception $e) {
        echo "回滚事务\n";
        throw $e;
    }
}

优先级控制

使用 #[Priority] 注解控制切面执行顺序,数字越小优先级越高。

#[Aspect]
class PriorityAspect
{
    #[Before("execution(* App\Service\*->*(..))")]
    #[Priority(Priority::HIGHEST)]  // 最先执行
    public function first(JoinPoint $joinPoint): void
    {
        echo "第一个执行\n";
    }

    #[Before("execution(* App\Service\*->*(..))")]
    #[Priority(100)]
    public function second(JoinPoint $joinPoint): void
    {
        echo "第二个执行\n";
    }
}

切入点表达式

支持的切入点表达式语法:

表达式 说明 示例
execution(* Class->method(..)) 执行方法 execution(* UserService->createUser(..))
execution(* Class->*(..)) 类的所有方法 execution(* UserService->*(..))
execution(* Namespace\*->*(..)) 命名空间下所有类的所有方法 execution(* App\Service\*->*(..))
within(Namespace\*) 命名空间下所有类 within(App\Controller\*)

通配符说明:

  • *:匹配任意数量的任意字符
  • ..:匹配任意参数列表
  • ?:匹配单个任意字符

JoinPoint API

JoinPoint 类提供了丰富的方法来获取方法调用的上下文信息:

$joinPoint->getClass();        // 获取目标类的反射对象
$joinPoint->getMethod();       // 获取目标方法的反射对象
$joinPoint->getThis();         // 获取目标对象实例
$joinPoint->getArguments();    // 获取方法参数
$joinPoint->setArguments([]);  // 设置方法参数
$joinPoint->getPointcut();     // 获取切入点表达式
$joinPoint->getResult();       // 获取返回值(After 通知)
$joinPoint->getMethodName();   // 获取方法名
$joinPoint->getClassName();    // 获取类名
$joinPoint->getArgument(0);    // 获取指定位置的参数

ProceedingJoinPoint API

ProceedingJoinPoint 继承自 JoinPoint,额外提供了控制原方法执行的能力:

$result = $joinPoint->proceed();                    // 使用原始参数执行
$result = $joinPoint->proceed(['newArg']);          // 使用新参数执行
$result = $joinPoint->proceedWithNamedParams([...]); // 使用命名参数执行
$closure = $joinPoint->getProceedClosure();         // 获取执行闭包

🏗️ 核心组件

src/
├── Attribute/               # 原生注解定义
│   ├── Aspect.php           # 切面标记
│   ├── Before.php           # 方法前执行
│   ├── After.php            # 方法后执行(无论异常)
│   ├── Around.php           # 环绕执行(可控制流程)
│   ├── Pointcut.php         # 切入点表达式
│   └── Priority.php         # 执行优先级
│
├── Contract/                # 接口契约
│   ├── AspectInterface.php
│   ├── JoinPointInterface.php
│   ├── ProceedingJoinPointInterface.php
│   └── AspectKernelInterface.php
│
├── Runtime/                 # 运行时核心
│   ├── JoinPoint.php        # 封装调用上下文
│   ├── ProceedingJoinPoint.php # Around 场景专用
│   └── AspectKernel.php     # 核心调度器
│
├── Reflection/              # 安全反射封装
│   ├── Reflector.php        # 安全获取类/方法/属性元数据
│   └── MetadataReader.php   # Attribute 元数据读取器
│
├── Exception/               # 自定义异常
│   └── AopException.php
│
└── Helper/                  # 工具函数
    └── Str.php              # 字符串匹配

🔧 框架集成

Laravel 集成

// app/Providers/AopServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Kode\Aop\Runtime\AspectKernel;

class AopServiceProvider extends ServiceProvider
{
    public function register(): void
    {
        $this->app->singleton(AspectKernel::class, function () {
            $kernel = AspectKernel::getInstance();
            $kernel->registerAspect(new \App\Aspects\LoggingAspect());
            $kernel->registerAspect(new \App\Aspects\TransactionAspect());
            $kernel->init();
            return $kernel;
        });
    }
}

Symfony 集成

// config/services.yaml
services:
    Kode\Aop\Runtime\AspectKernel:
        factory: ['@App\Aop\AspectKernelFactory', 'create']
        calls:
            - [init, []]

    App\Aop\AspectKernelFactory:
        class: App\Aop\AspectKernelFactory

Hyperf 集成

// config/autoload/dependencies.php
<?php

return [
    Kode\Aop\Runtime\AspectKernel::class => function () {
        $kernel = Kode\Aop\Runtime\AspectKernel::getInstance();
        $kernel->registerAspect(new \App\Aspect\LoggingAspect());
        $kernel->init();
        return $kernel;
    },
];

🧪 测试

运行测试:

composer test

运行代码覆盖率:

composer coverage

静态分析:

composer analyse

📋 系统要求

  • PHP >= 8.1
  • Composer >= 2.0
  • kode/attributes ^1.0

📄 许可证

Apache License 2.0

🤝 贡献

欢迎提交 Issue 和 Pull Request!

📮 联系方式

kode/aop 适用场景与选型建议

kode/aop 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 24 次下载、GitHub Stars 达 1, 最近一次更新时间为 2025 年 09 月 19 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「aop」 「aspect」 「proxy」 「attribute」 「php81」 「php82」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 kode/aop 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 kode/aop 我们能提供哪些服务?
定制开发 / 二次开发

基于 kode/aop 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 24
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 1
  • 点击次数: 33
  • 依赖项目数: 1
  • 推荐数: 1

GitHub 信息

  • Stars: 1
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: Apache-2.0
  • 更新时间: 2025-09-19