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 }
时间: 2024-10-25 22:40:28

PHP一个类AOP的实现的相关文章

发现一个类的方法不够用时,可以使用的3种方法可以增强

A.创建子类,改写需要增强的方法B.包装设计模式//1.定义一个类,实现与被增强对象相同的接口//2.在类中定义一个变量,记住被增强对象//3.定义一个构造对象,接受被增强对象//4.覆盖想增强的方法//5.对于不想增强的方法,直接调用目标对象的方法C.使用动态代理(aop面向切面编程) //视频讲解: 方立勋javaweb30天教程-就业办16/day16avi/03-数据库连接池.avi https://pan.baidu.com/s/1eQBvrRc#list/path=%2F%E6%96

模拟spring - 动手写一个spring AOP

一.前言 AOP (Aspect Oriented Programing) - 面向切面编程,它主要用于日志记录.性能分析.安全控制.事务处理.异常处理等方面. AOP主要使用JDK的反射和动态代理,AOP代理其实是由AOP框架动态生成的一个对象,该对象可作为目标对象使用,AOP代理包含了目标对象的全部方法,但AOP代理的方法与目标对象的方法存在差异:AOP方法在特定切入点添加了增强处理,并回调了目标对象的方法. 动态代理的文章请参考:http://blog.csdn.net/zdp072/ar

一个类有多大

#include <iostream> using namespace std; class A{}; class B { int b; char c; }; class C { int c1; static int c2; }; int C::c2 = 1; class D:public C,public B{ int d; }; int main() { cout<<"sizeof(A)="<<sizeof(A)<<endl; cou

C#利用反射,遍历获得一个类的所有属性名,以及该类的实例的所有属性的值

转自goldeneyezhang原文 C#利用反射,遍历获得一个类的所有属性名,以及该类的实例的所有属性的值 C#利用反射,遍历获得一个类的所有属性名,以及该类的实例的所有属性的值总结: 对应某个类的实例化的对象tc, 遍历获取所有属性(子成员)的方法(采用反射): Type t = tc.GetType();//获得该类的Type //再用Type.GetProperties获得PropertyInfo[],然后就可以用foreach 遍历了 foreach (PropertyInfo pi

Java语言程序设计 上机实验4 掌握声明接口、一个类实现接口的声明和使用方法

Java语言程序设计 上机实验4 实验目的: 理解接口的作用,理解接口和实现接口的类的关系,掌握声明接口.一个类实现接口的声明和使用方法:熟悉Java语言包和实用包中的常用类. 实验内容:(*)为选做 声明圆柱体类Cylinder,继承椭圆类Ellipse(实现周长Perimeter接口和面积Area接口),为圆柱体类设计较为全面的构造方法,并实现体积Volume接口,计算表面积和体积. 将Java的若干关键字(15个以上)保存在一个字符串数组中,对其按升序排列,再采用顺序查找和二分法查找,判断

java进阶之反射:反射基础之如何获取一个类以及如何获取这个类的所有属性和方法(1)

java学习一段时间之后,大家可能经常会听到反射这个词,那么说明java已经学习到一个高一点的层次了.接下来我会一步步和大家一起揭开java高级特性反射的神秘面纱. 首先介绍下类对象这个概念,可能会经常用到这个概念: 类对象:java中有句很经典的话"万事万物皆对象",相信大家都不陌生,这句话告诉了我们java的特征之一,那就是面向对象.java中类的概念我们都很熟悉,既然万事万物皆是对象,那么类是谁的对象呢?<对象的概念:一个类的实例>换句话说,类是谁的实例.如此就有了类

MFC中怎样完全删除一个类

测试环境:Windows7 32bit.VC++6.0 VC++6.0中添加类很方便,不过删除一个类就没有那么直观了.如果想删除了一个类,其实只需要这样做: 在FileView中的Source Files和Header Files中分别移除类对应的.cpp和.h文件(点击该文件,然后按Delete即可移除,文件仅从工程中移除,并没有在工程目录下被删除) 关闭VC++6.0,然后删除工程目录下的.clw文件,以及类对应的.cpp和.h文件 重新启动VC++6.0,选择View中ClassWizar

ExtJs--07--Ext.define定义一个类的过程

Ext.onReady(function(){ //Ext定义一个类 Ext.define( "Person", { config:{ name:"jack", age:22 }, fangfa:function(){ Ext.Msg.alert("标题信息","提示内容信息") } , constructor:function(config){ //测试构造器调用没有及参数传递进来没有 // for(var attr in

如何限制一个类只在堆上分配和栈上分配(StackOnly HeapOnly)

[本文链接] http://www.cnblogs.com/hellogiser/p/stackonly-heaponly.html [题目] 如何限制一个类只在堆上分配和栈上分配? [代码] C++ Code 1234567891011121314   class StackOnly { private:     void *operator new(size_t size) {}; }; class HeapOnly { public:     void destroy(); private