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  */
19 class 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. [代码]测试代码     

01 class AOPWorker{
02     public function testAOP(){
03         Debugger::print_r(
04             "\n工人:我要做一大堆操作了
05                 \n工人:... ...
06                 \n工人:好了 做完了\n");
07         return 'OK';
08     }
09  
10 }
11  
12  
13 public function testAOP(){// test aop  测试入口
14         $aop = Wrapper::wrap(new AOPWorker());
15         $aop->testAOP(33347);
16 }
17  
18  
19  
20 class 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  
34 class 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 }

posted on 2014-08-25 09:56  山冈龙  阅读(1498)  评论(0编辑  收藏  举报

导航