實際開發需求中使用到 AOP Aspect

AR414發表於2020-10-11

前言

什麼是AOP,這裡就不深入講一些理論,這裡主要是闡述AOP中的Aspect(切面),主要是以實際開發中使用到AOP的一個例子來說明比較有深刻的印象。

例如 ThinkPHP 中的控制器前置操作beforeActionList,又或者中介軟體,還有自己建立一個基類來實現等等,以上方法在某種意義上也有一些AOP的思想(一般來說 AOP是指將幾個類共有的程式碼,抽取到一個切片中,等到需要時再切入物件中去,從而改變其原有的行為),AOP像OOP一樣,只是一種程式設計正規化,AOP並沒有規定說,實現AOP協議的程式碼,要用什麼方式去實現。我的理解是 將程式碼切入到類的指定方法、指定位置上的程式設計思想就是面向切面的程式設計,把和主業務無關的事情,放到程式碼外面去做,對原有程式碼毫無入侵性。

AOP可能很多人只是瞭解過並沒有真正使用到實際的專案中,我認為只有在實際專案中去實現才算是有意義的(最好先在個人專案中實踐一下)

實踐

環境

閘道器中某個服務使用了hyperf 2.0

需求

有分頁的資料中將Laravel分頁器的結果後設資料欄位轉為閘道器分頁規範資料欄位

這個的需求有很多方法實現,這裡我使用了將 提供分頁資料的控制器中的方法 統一進行切面處理,這樣的做法,對原有程式碼毫無入侵性,這就是AOP的好處了,把和主業務無關的事情,放到程式碼外面去做

Laravel 分頁器預設欄位

{
   "total": 50,
   "per_page": 15,
   "current_page": 1,
   "last_page": 4,
   "first_page_url": "http://laravel.app?page=1",
   "last_page_url": "http://laravel.app?page=4",
   "next_page_url": "http://laravel.app?page=2",
   "prev_page_url": null,
   "path": "http://laravel.app",
   "from": 1,
   "to": 15,
   "data":[
        {
            // Result Object
        },
        {
            // Result Object
        }
   ]
}

閘道器分頁規範欄位

{
   "total": 50,
   "current_page": 1,
   "last_page": 4,
   "data":[
        {
            // Result Object
        },
        {
            // Result Object
        }
   ]
}

具體實現方法

hyperf 2.0 中使用 Aspect 切面
通過配置要切入的類,這裡切入的是面向有分頁資料的控制器中的具體方法
例如 TestController::getListTest1Controller::getList 這兩個方法提供了分頁資料

定義切面(Aspect)
一般而言,我們管切入到指定類指定方法的程式碼片段稱為切面,而切入到哪些類、哪些方法則叫切入點

class PageResultAspect extends AbstractAspect
{

  public $classes = [
    TestController::class . '::' . 'getList',
    Test1Controller::class . '::' . 'getList',
  ];

  public $annotations = [];

  public function process(ProceedingJoinPoint $proceedingJoinPoint)
  {
        // 切面切入後,執行對應的方法會由此來負責 
      // $proceedingJoinPoint 為連線點,通過該類的 process() 方法呼叫原方法並獲得結果
      $result = $proceedingJoinPoint->process();

      //將結果進行統一處理
      if(isset($result['first_page_url'])) {
          unset($result['first_page_url']);
          unset($result['last_page_url']);
          unset($result['next_page_url']);
          unset($result['path']);
          unset($result['prev_page_url']);
          unset($result['per_page']);
          unset($result['from']);
          unset($result['to']);
      }

      return $result;
  }

}



本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章