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
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;
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}
页:
[1]