PHP之AOP实践
AOP,全称为Aspect Oriented Programming(面向切面编程),是一种编程思想,旨在将横向的功能抽离,形成“切面”。在 PHP 中,可以使用一些框架或者库来实现 AOP,本文将介绍其中一种实现方式 —— Go! AOP PHP。
Go! AOP PHP 简介
Go! AOP PHP 是一个 AOP 库,由于使用了 PHP 强大的“魔术方法”机制,因此实现了非常简单易用的 AOP。
使用 Go! AOP PHP,可以快速地、不侵入地实现以下功能:
- 日志记录
- 性能统计
- 缓存优化
- 事务管理
- 权限控制
安装
安装 Go! AOP PHP 通常可以通过 Composer 快速完成:
composer require goaop/framework
基本使用
使用 Go! AOP PHP 需要定义一个 Aspect,它是一个横向的功能,可以理解成“切面”。在 Aspect 中我们可以定义一些 Advise(通知),它们对应了不同的“切点”,例如 before、after、around 等等。
实现一个带有日志记录的“切面”可以这样写:
use Go\Aop\Aspect;
use Go\Aop\Intercept\MethodInvocation;
use Go\Lang\Annotation\Before;
class LogAspect implements Aspect
{
/**
* @Before("execution(public App\Services\*->*(..))")
*/
public function beforeMethodCall(MethodInvocation $invocation)
{
$className = get_class($invocation->getThis());
$methodName = $invocation->getMethod()->name;
$logger->info(sprintf('Calling %s::%s()', $className, $methodName));
}
}
在上例中,我们定义了一个名为 LogAspect 的切面,使用注解 @Before("execution(public App\Services*->*(..))") 来匹配所有 App\Services 命名空间下的“公有方法”作为“切点”,在这些方法执行之前记录日志。
定义完 Aspect 之后,我们还需要使用 factory 来创建一个代理类,它会继承原始类,并在其中加入 Aspect 实例中定义的 Advise:
use Go\Aop\Features;
use Go\Aop\Support\AopUtils;
$aspectContainer = AopUtils::getInstance()->getContainer();
$aspectContainer->registerAspect(new LogAspect());
$features = new Features();
$features->setGeneratedClassesTargetDir(__DIR__ . '/gen');
$features->setAopCacheDir(__DIR__ . '/cache');
$aspectKernel = AspectKernelFactory::createKernel('dev', true, $features);
$aspectKernel->init();
$proxyGenerator = $aspectKernel->getContainer()->get('goaop.proxy_generator');
$proxyGenerator->generateProxyClass(App\Services\MyService::class);
完成以上步骤后,就可以将原始类 MyService 的实例替换为代理类的实例,这样所有调用 MyService 实例的方法都会被代理类拦截,并执行 LogAspect 中的 Advise。
总结
本文介绍了 PHP 中一种实现 AOP 的库 —— Go! AOP PHP,介绍了它的安装和基本使用方法。 AOP 编程思想是非常重要的思想,可以帮我们在复杂应用中快速或灵活地实现各种功能,例如日志记录、缓存优化、事务管理等等。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:php之aop实践 - Python技术站