swoft之AOP切面的基本使用

首页 / swoft / 正文

1. 什么是AOP

AOP(Aspect-oriented programming)即 面向切面的程序设计,AOP 和 OOP(Object-oriented programming)面向对象程序设计一样都是一种程序设计思想,AOP 只是 OOP 的补充和延伸,可以更方便的对业务代码进行解耦,从而提高代码质量和增加代码的可重用性。后面的篇章会结合实际案例,教会大家理解并学会使用 AOP。

2. 调用场景

  • 需要记录某个接口请求的日志(接收参数,返回参数,执行时间等)
  • 调用出现异常时,触发相关操作处理(发送邮件通知等等)
  • 调用方法前进行权限校验等等
优点就是,在不改变原有方法代码的情况下实现你想要实现的额外功能.

3. 案例

我们那swof代码中的首页代码来示范

 */
public function index(): Response
{
    /** @var Renderer $renderer */
    $renderer = Swoft::getBean('view');
    $content  = $renderer->render('home/index');
    $end_time = microtime(true);
    return context()->getResponse()->withContentType(ContentType::HTML)->withContent($content);
}

当我们想对上边的代码加一个运行时间是,按照之前的写法,我们可能会写成这样:

/**
 * @RequestMapping("/")
 * @throws Throwable
 */
public function index(): Response
{
    $begin_time = microtime(true); // 获取一个毫秒时间
    /** @var Renderer $renderer */
    $renderer = Swoft::getBean('view');
    $content  = $renderer->render('home/index');
    $end_time = microtime(true); // 在获取一个毫秒时间
    vdump("运行时间为:", round(($end_time - $begin_time) * 1000, 3)); // 拿开始时间减去结束时间 乘以1000 得到一个描述,在保留3位小数
    return context()->getResponse()->withContentType(ContentType::HTML)->withContent($content);
}

运行结果是这样的:(在控制台中查看结果)

PRINT ON App\Http\Controller\HomeController(41):
string(16) "运行时间为:"
float(2.058)

这样有个缺点就是,只是计算了当前$bengin_time$end_time之间代码的运算时间,并且我们修改了原方法,那么我们如何才能不通过修改源代码的方式,也能得到运算时间呢?

我们首先先顶一个切面类,类似于这样:

<?php declare(strict_types=1);

namespace App\Aspect;

use App\Http\Controller\HomeController;
use Swoft\Aop\Annotation\Mapping\After;
use Swoft\Aop\Annotation\Mapping\Aspect;
use Swoft\Aop\Annotation\Mapping\Before;
use Swoft\Aop\Annotation\Mapping\PointBean;
use Swoft\Aop\Point\JoinPoint;

/**
 * @Aspect(order=1) # 优先级, 数字越小则优先执行。
 *
 * @PointBean(include={HomeController::class}) # 这里指的是定义切入目标。注意需要use引入一下这个类
 */
class YingxiaozhuAspect {

    /** @var float 执行开始 */
    private $time_begin;

    /**
     * 前置通知
     *
     * @Before()
     */
    public function beforeAdvice()
    {
        // 起点时间
        $this->time_begin = microtime(true);
    }

    /**
     * 后置通知
     *
     * @After()
     *
     * @param JoinPoint $joinPoint
     */
    public function afterAdvice(JoinPoint $joinPoint)
    {
        /** @var float 执行结束 */
        $timeFinish = microtime(true);
        $method = $joinPoint->getMethod();
        $runtime = round(($timeFinish - $this->time_begin) * 1000, 3);
        echo "{$method} 方法,本次执行时间为: {$runtime}ms \n";
    }
}

重启服务,访问首页查看一下结果:

index 方法,本次执行时间为: 4.072ms 

关注颖小主其他相关文章,后续带你理解AOP原理,前置通知后置通知返回通知异常通知环绕通知

打赏
评论区
头像
文章目录