首页 > 代码库 > PHP一个类AOP的实现

PHP一个类AOP的实现

由于项目有一个需求,需要在原来的代码上做一个封装. 由于不想修改原有代码, 查了一下, PHP没有方便的支持AOP的方法,于是参考了网上一些文章,写了个包装器, 可以在不修改原有代码的基础上为函数添加before和after实现.

 
标签: <无>
 

代码片段(3)[全屏查看所有代码]

1. [代码]核心类     

01<?php
02 
03/**
04 * 包装器(Wrapper).
05 * Wrapper是一个AOP_LIKE的实现. 也可以看作监听者模式的实现.
06 * 一个Wrapper报装了一个对象(source). source可以是任意对象(不包括数组及原子类型),甚至是一个Wrapper.
07 *
08 * 包装器可以任意添加饰品(Decoration).通过Wrapper调用source的函数的流程将是:
09 *  unpacking --> teardown --> open --> setup --> packing.
10 *
11 *  例如调用source->doXX(),各个流程将是:
12 *  unpacking:  解包. 这是调用任意source的函数都会调用的方法;
13 *  teardown:   撕掉饰品. 对于Wrapper中的每个Decoration,调用其before()函数;
14 *  open:       真正调用source->doXX()函数;
15 *  setup:      重新贴上饰品. 对于Wrapper中的每个Decoration,调用其after()函数;
16 *  packing:    重新打包.  这是调用任意source的函数都会调用的方法;
17 *
18 */
19class Wrapper{
20    private $source;
21 
22    /**
23     * @var bool
24     */
25    private $undecorated;
26 
27    /**
28     * @var array[Decoration]
29     */
30    private $decorations=array();
31 
32    public function __construct($source){
33        $this->source = $source;
34    }
35 
36    public function __call($name,$parameters){
37        $this->unpacking($name,$parameters);
38        $this->tearDown($name,$parameters);
39 
40        // opening
41        if(method_exists($this->source, $name)){
42            $retval = call_user_func_array(array($this->source,$name),$parameters);
43        }
44 
45        $this->setup($retval,$name,$parameters);
46        $this->packing($retval,$name,$parameters);
47 
48        return $retval;
49    }
50 
51    public function unpacking($name,$parameters){
52    }
53 
54    public function packing($name,$parameters){
55    }
56 
57    public function tearDown($name,$parameters){
58        if($this->undecorated){
59            return;
60        }
61        foreach ($this->decorations as $d){
62            $d->before($name,$parameters);
63        }
64    }
65 
66    public function setup($retval,$name,$parameters){
67        if($this->undecorated){
68            return ;
69        }
70        foreach ($this->decorations as $d){
71            $d->after($retval,$name,$parameters);
72        }
73    }
74 
75    public function decarate($decoration){
76        $this->decorations[] = $decoration;
77    }
78 
79 
80 
81    public static function wrap($source){
82        //  wrap the source
83        $wrapperConfig = app()->wrappers[get_class($source)];
84        if($wrapperConfig){
85            $wrapperClass $wrapperConfig[‘class‘];
86            $wrapper new $wrapperClass($source);
87 
88            foreach ($wrapperConfig[‘decorations‘as $item){
89                $decoration new $item;
90                $wrapper->decarate($decoration);
91            }
92        }
93        return $wrapper?$wrapper:$source;
94    }
95 
96}
97 
98?>

2. [代码]配置     

01‘wrappers‘=>array(
02        ‘ContentService‘=>array(
03                ‘class‘=>‘ContentWrapper‘,
04                ‘decorations‘=>array(
05                        ‘DasaiContentDecoration‘,
06                )
07        ),
08        ‘AOPWorker‘=>array(//for test
09            ‘class‘=>‘DiagnosisWrapper‘,
10            ‘decorations‘=>array(
11                ‘DasaiDiagnosisDecoration‘
12            ),
13        ),
14),

3. [代码]测试代码     

01class AOPWorker{
02    public function testAOP(){
03        Debugger::print_r(
04            "\n工人:我要做一大堆操作了
05                \n工人:... ...
06                \n工人:好了 做完了\n");
07        return ‘OK‘;
08    }
09 
10}
11 
12 
13public function testAOP(){// test aop  测试入口
14        $aop = Wrapper::wrap(new AOPWorker());
15        $aop->testAOP(33347);
16}
17 
18 
19 
20class DiagnosisWrapper extends Wrapper{
21 
22    public function unpacking($name$parameters){
23        echo "\nDiagnosisWrapper:喂,有人调用$name,我要解包了.\n";
24    }
25 
26 
27    public function packing($retval,$name$parameters){
28        echo "\nDiagnosisWrapper:喂,调用$name,结果为$retval,重新打包好了.\n";
29    }
30}
31 
32 
33 
34class DasaiDiagnosisDecoration extends Decoration {
35    public function before($name,$parameters){
36        echo "\r\nDasaiDiagnosisDecoration:开始调用$name,已经告诉张三李四了.\n";
37    }
38 
39    public function after($retval,$name,$parameters){
40        echo "\nDasaiDiagnosisDecoration:结束调用$name,告诉霍金和Sheldon了.\n";
41    }

42}

PHP一个类AOP的实现