面向切面程式設計(AOP),也可以成為契約程式設計。好處和作用有很多。比如降低模組之間的耦合度,進行程式碼擦除減少重複程式碼。
在工作過程中,因為要對一部分方法,進行日誌環繞處理。如果用代理模式的話,顯得過於臃腫。所以,想到了Java的AOP。由於沒有找到合適的包,所以自己就手擼了一個。由於比較簡單,所以也懶得打包了,目前只實現了簡單的函式代理。(流程圖如下)
實現程式碼
AOP實現類
<?php
namespace App\Http\Intercept\Proxy;
use App\Http\Intercept\Interceptor;
use App\Http\Intercept\InvokeEnhance\Invocation;
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2021/10/8
* Time: 15:14
*/
class ProxyBean
{
private $target = null; //被代理類
private $args = null;// 被代理的構造引數
private $interceptor = null; //代理類
private $ex;
/**
* @param $target //被代理類
* @param $args //被代理的構造引數
* @param Interceptor $interceptor //代理類
* @return ProxyBean
*/
public static function getProxyBean($target,$args,Interceptor $interceptor){
$proxyBean = new ProxyBean();
//被代理的類
$proxyBean->target = $target; //被代理類
$proxyBean->args = $args; //被代理的構造引數
$proxyBean->interceptor = $interceptor; //代理類
return $proxyBean;
}
/**
* 魔術方法 - 呼叫不存在的方法是,觸發代理實現
* @param $name
* @param $arguments
*/
public function __call($name,$arguments) {
return $this->invoke($this->target,$this->args,$name,$arguments);
}
/**
*代理執行
* @param $target //被代理類
* @param $args //被代理類構造引數
* @param $name //被代理類執行方法
* @param $arguments //被代理類執行方法-引數
* @return void|null
*/
public function invoke($target,$args,$name,$arguments){
$exceptionFlag = false;
$retObj = null;
$invocation = new Invocation($target,$args,$name,$arguments);
try {
if ($this->interceptor->before() && $this->interceptor->useAround()){
$retObj = $this->interceptor->around($invocation);
}else{
$retObj = $invocation->proceed();
}
}catch (\Exception $ex){
$exceptionFlag = true;
$this->ex =$ex;
}
$this->interceptor->after();
if ($exceptionFlag){
$this->interceptor->afterThrowing($ex);
}else{
$this->interceptor->afterReturning();
return $retObj;
}
return null;
}
}
契約介面
<?php
namespace App\Http\Intercept;
use App\Http\Intercept\InvokeEnhance\Invocation;
/**
* AOP 約定介面標準
* Created by PhpStorm.
* User: Administrator
* Date: 2021/10/8
* Time: 14:56
*/
interface Interceptor
{
//執行前
public function before() :bool;
//執行後
public function after();
//環繞
public function around(Invocation $invocation);
//執行後執行
public function afterReturning();
//捕獲執行錯誤
public function afterThrowing(\Exception $ex);
//是否啟用環繞
public function useAround() :bool;
}
契約自定義類
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2021/10/8
* Time: 15:29
*/
namespace App\Http\Intercept;
use App\Http\Intercept\InvokeEnhance\Invocation;
class DatabaseWmsLogInterceptor implements Interceptor
{
public function before(): bool
{
var_dump('before......<br>');
return true;
}
public function after()
{
// TODO: Implement after() method.
}
public function afterReturning()
{
var_dump('afterReturning...<br>');
}
public function afterThrowing(\Exception $ex)
{
var_dump('afterThrowing...'.$ex->getMessage());
}
public function useAround(): bool
{
return true;
}
public function around(Invocation $invocation)
{
echo '<br>================around before...==================<br>';
var_dump('around before...<br>');
var_dump($invocation->getMethodargs());
echo '<br>=================around before...=================<br>';
$obj = $invocation->proceed();
echo '<br>================around after...==================<br>';
var_dump('<br>around after...<br>');
var_dump($obj);
echo '<br>================around after...==================<br>';
return $obj;
}
}
被代理類
<?php
/**
* Created by PhpStorm.
* User: Administrator
* Date: 2021/10/8
* Time: 15:26
*/
namespace App\Services\Test;
use App\Services\Test\InInterface\HelloService;
class HelloServiceImpl implements HelloService
{
public function sayHello($name)
{
if (empty($name)){
throw new \RuntimeException("parameter is null");
}
var_dump('hello:'.$name);
}
public function sayGoodBy($name,array $arr)
{
var_dump($name.':sayGoodBy:'.json_encode($arr));
return $arr;
}
public static function good($name){
var_dump($name);
return $name;
}
}
實現用例
/**
* aop 約定式程式設計
*
* @param int $id
* @return \Illuminate\View\View
*/
public function testDatabaseWmsLogInterceptor()
{
$proxy = ProxyBean::getProxyBean(HelloServiceImpl::class,[],app(DatabaseWmsLogInterceptor::class));
//$proxy->sayHello();
echo '<br>';
$result = $proxy->sayGoodBy('小狗',['one','two']);
var_dump($result);
//return view('testDemo');
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結