PHP AOP 实现

AOP VS OOP

AOP(Abstract Oriented Programming),面向切面编程。AOP是OOP的补充和完善,OOP通过封装继承多态建立一种从上到下的系统层次,但对于与系统业务逻辑无关,每一层次都涉及的功能却无能为力,例如日志。这种分散到各处的被称为横切cross-cutting。

AOP基本概念

切面(Aspect)
一个关注点的模块化,这个关注点横切多个对象。例如logging,caching,transaction

连接点(Joinpoint):
程序执行过程中明确的点,如方法的调用,特定的异常被抛出或属性的获取。

通知(Advice):
切面在特定连接点采取的行动。

切入点(Pointcut):
指定一个通知将被引发的一系列连接点的集合

引入(Introduction):
添加方法或字段到被通知的类。

织入(Weaving):
组装切面来创建一个被通知对象。这可以在编译时或加载时完成,也可以在运行时完成。

伪AOP

PHP魔术方法实现伪PHP。
代码执行未定义的方法时会调用__call方法,通过重定义__callf方法以实现AOP。

  1. 父类log包含call方法
  2. 子类user继承父类并定义_show方法
  3. 调用子类show方法
  4. 无法找到执行从父类继承的call方法,加载子类的_show方法。
class log {
    function __call($method,$args) {
        $method = "_$method";
        echo 'log begins...
'
; $return = call_user_func_array(array($this, $method), $args); echo 'log ends...
'
; return $return; } } class user extends log { function _show() { echo 'This is show.
'
; } } $news = new user(); $news->show(); //运行结果: //log begins... //This is show. //log ends...

也可以改进这种方法,将AOP实现部分进行包装,添加配置信息字段。使实现类不用继承父类的call方法。

升级版-伪AOP

AOP的实现可以通过读取类,将类解包,添加需要的操作,将类重新打包成新类调用。

PHP AOP 实现_第1张图片

创建需要监听的类。当调用user中方法时候实现监听,记录log。

class user{
    public function show(){
        echo 'User SHOW.
'
; } }

创建配置信息和wrap类,wrap实现aop部分功能。

//配置信息
$wrappers = array(
    'user'=>array(
        'class'=>'userWrapper'
    )
);
class Wrapper{
    private $source;
    public function __construct($source){
        $this->source = $source;
    }
    public function __call($name,$para){
        $this->before($name,$para);
        if (method_exists($this->source, $name)){
            $return = call_user_func_array(array($this->source,$name), $para);
        }
        $this->after($name,$para);
        return $return;
    }
    //将类进行包装
    public static function wrap($source){
        $wrapperConfig = $GLOBALS['wrappers'][get_class($source)];
        if ($wrapperConfig){
            $wrapperClass = $wrapperConfig['class'];
            $wrapper = new $wrapperClass($source);
        }
        return $wrapper?$wrapper:$source;
    }
}
class userWrapper extends Wrapper{
    public function before($name,$para){
        echo 'Logging begins...
'
; } public function after(){ echo 'Logging ends...
'
; } } //测试 $user = Wrapper::wrap(new user()); $user->show(); //测试结果: //Logging begins... //User SHOW. //Logging ends...

这种方法虽然实现了aop的部分功能。但对代码存在污染,并未做到真正的切面剥离。

你可能感兴趣的:(AOP)