Foreword

Before introducing AOP, let's briefly explain that AOP is just a programming idea like OOP. AOP is just a supplement and extension of OOP. It can more easily decouple business code, improve code quality, and increase code. Reusability. The following chapters will combine the actual cases to teach everyone to understand and learn to use AOP.

Scene case

Let's start with the log record to lead you to understand the advantages of AOP aspect programming.

First we assume that we have the following requirements:

  • It is necessary to make a call log record for an interface, and record the call details of the interface (call parameters, return results, etc.).
  • When an exception occurs in the interface call, special processing such as logging, notifying our operation and maintenance partners, etc.

As above, we define a simple requirement. Next, let's implement it. Let's not consider AOP first. Let's use the OOP idea you are familiar with to complete the above requirements.

OOP implementation

Suppose we have one of the following business interfaces

 <?php declare(strict_types=1);
/**
 * 订单服务类
 *
 * @since 2.0
 */
class OrderServer
{
    /**
     * 下单接口
     *
     * @param $productName //商品名字
     * @param $number //购买数量
     * @param $uid //用户id
     *
     * @return array        //订单参数
     */
    public function order($productName, $number, $uid): array
    {
        $price = 1000;
        $total = $price * $number;
        $data = [
            'product_name' => $productName,
            'price' => $price,
            'number' => $number,
            'total' => $total,
            'order_id' => uniqid($uid . time() . $total)
        ];
        return $data;
    }
} 

Under the traditional OOP idea, we might write a class that inherits from our OrderServer and then rewrite its order method, and then replace it with our own defined class where we use the OrderServer class.

The sample code is as follows: First we write a subclass that inherits from OrderServer

 <?php declare(strict_types=1);
/**
 * Class InheritOrderServer
 *
 * @since 2.0
 */
class InheritOrderServer extends OrderServer
{
    /**
     * @param $productName
     * @param $number
     * @param $uid
     *
     * @return array
     * @throws Exception
     */
    public function order($productName, $number, $uid): array
    {
        //TODO::在这里我们记录接口调用时传过来的参数
        try {
            $result = parent::order($productName, $number, $uid);
            //TODO::这里可以处理父类方法返回的结果 然后返回结果进行后续处理
            return $result;
        } catch (Exception $e) {
            //TODO::如果有出错异常,在这里我们处理出错的日志记录等操作之后继续将异常抛出
            throw $e;
        }
    }
} 

Next, go ahead and find the place where we originally called OrderServer , and change the original call to the inheritance class InheritOrderServer we will write later.

 <?php declare(strict_types=1);
//$order = new OrderServer(); //屏蔽掉原先的旧的业务调用
$order = new InheritOrderServer();//修改为我们新继承的子类
$order->order('iPhone XR', 200, 10000); 

At this point, after the above operation, we seem to be able to meet the business needs to complete the log record function, but you will find the process and its complexity, code coupling is serious, polluting the order method, if there are 100 calls in the old business, Then you have to go to the business code to modify 100 code. If you have been trying to solve these problems with OOP, it seems to be very difficult, because almost all are highly coupled intrusive solutions.

At this time, you may think of using middleware, interceptors, etc., but these are actually a design pattern based on AOP thinking. In fact, AOP is based on the extension and supplement of OOP. He is an idea, a design pattern.

AOP implementation

Next we will introduce the concept of AOP based on the above example, telling everyone what is AOP (what), how to use AOP (how), why use AOP (why).

What is AOP

definition

Aspect-oriented programming (AOP, also translated as aspect-oriented programming, section-oriented programming) is a programming paradigm in computer science that aims to further cross-cutting concerns with business entities. Separate to increase the modularity of the program code. --"Wikipedia"

In the software industry, AOP is the abbreviation of Aspect Oriented Programming, which means: face-oriented programming, a technique for unified maintenance of program functions through pre-compilation and runtime dynamic agents. --"Baidu Encyclopedia"

The main function of AOP is to add new functions to the original functions without invading the original function code.

We all know that OOP is actually an abstract wrapper on our functional properties, methods, and a clear division of logical units, but OOP can only perform vertical abstract encapsulation, which can not solve horizontal repetitive problems well, while AOP This problem is solved very well. Please see the following illustration below.

OOP

As shown in the figure above, we can see that we have two class 订单类 . The 用户类 has been encapsulated by related functions, but when it encounters similar permission checks, the repetitive operation of logging does not have a good way to solve it. The idea of AOP is to cut out these functions horizontally and then weave them in at the appropriate time, as shown in the figure.

OOP

This is what AOP does as shown.

AOP is just like OOP. It has some related technical terms like OOP. I will introduce these terms to you below.

Interpretation of related terms

First, let’s start with a rough explanation of related terms.

  • Advice

    It is the function you want, the function that is implemented by the method, that is, the security, transaction, log, etc. mentioned above. You should first define the function with the method first, and then use it where you want to use it.

  • Connection point (JoinPoint)

    It is the place where you can place the advice. The basics of each method are before and after (both of them are OK), or when the exception is thrown, it can be the connection point. Swoft only supports method-level connection points. . Just remember that the front and back of the method are the connection points.

  • Pointcut

    This is the specific method to define the cut, why? Assume that there are 10 methods in a class, each method has multiple join points (JoinPoint), but you do not want to use notifications in all methods (weaving ), you only want to weave some of these methods, then use this pointcut to define the specific method.

  • Aspect

    It is a combination of advice and pointcut. The notice explains what to do, and the entry point indicates where to do it. In general, the connection point is specified when the pointcut is specified. The connection point is written separately for the sake of better understanding.

  • Introduction

    Just use our new classes and methods in the target class.

  • Target

    The target class mentioned in the introduction, that is, the object to be notified, that is, the real business logic, can be woven into the face without knowing it.

  • Proxy

    The whole set of AOP mechanisms is through the proxy, and Swoft uses the PHP-Parse class library to implement AOP more conveniently.

  • Weaving

    The process of applying a facet to a target object to create a new proxy object.

How to use AOP

Here is mainly to introduce how to use AOP in SWOFT

The special convenience of using AOP in SWOFT, we only need to declare a facet class by 注解 . Here is a simple demonstration. For a detailed description of the AOP class, please refer to the subsequent statement section.

 <?php declare(strict_types=1);

namespace App\Aspect;

use Swoft\Aop\Annotation\Mapping\Aspect;
use Swoft\Aop\Annotation\Mapping\Before;
use Swoft\Aop\Annotation\Mapping\PointBean;

/**
 * AOP切面类
 * 
 * @since 2.0
 *
 * 声明切面类
 * @Aspect(order=1)
 *
 * 使用注解定义切入点
 * @PointBean(include={"App\Http\Controller\TestExecTimeController"})
 */
class CalcExecTimeAspect
{
    /**
     * 定义通知链接点
     * @Before()
     */
    public function before()
    {
        //TODO::这里做具体的通知(Advice)
    }
} 

Complete the above case using Avo of Svoft

So far we have reviewed the scenario case mentioned at the beginning of this chapter. Here we use the AOP of the Swoft framework to quickly implement the requirements in the case.

 <?php declare(strict_types=1);

namespace App\Aspect;

use Swoft\Aop\Annotation\Mapping\Aspect;
use Swoft\Aop\Annotation\Mapping\Before;
use Swoft\Aop\Annotation\Mapping\After;
use Swoft\Aop\Annotation\Mapping\PointBean;

/**
 * AOP切面类
 * 
 * @since 2.0
 *
 * 声明切面类
 * @Aspect(order=1)
 *
 * 使用注解定义切入点
 * @PointBean(include={"OrderServer::class"})
 */
class CalcExecTimeAspect
{
    /**
     * 定义通知链接点
     * @Before()
     */
    public function before()
    {
        //TODO::在这里我们记录接口调用时传过来的参数
    }

     /**
      * 定义通知链接点
      * @AfterReturning()
      */
     public function afterReturning()
     {
         //TODO::这里可以处理方法返回的结果
     }

     /**
       * 定义通知链接点
       * @AfterThrowing()
       */
      public function afterThrowing()
      {
          //TODO::如果有出错异常,在这里我们处理出错的日志记录等操作

      }
} 

As above, with AOP we can do this very quickly. For a more complete use case, please see the chapter on usage .

/docs/2.x/en/aop/index.html
progress-bar