php的AOP编程实例

最近研究下php下面的AOP实现,在网上也看到不少的文章,老王在他的手册里利用魔术方法实现准AOP 这个方法很好。

下面是实例代码
[cce_php]
//应用程序中某个业务逻辑类
class BIZ
{
public function foobar(){
echo ‘业务逻辑<br />’;
}
}

//业务逻辑类的包装类
class AOP
{
private $instance;

public function __construct($instance){
$this->instance = $instance;
}

public function __call($method, $argument){
if(! method_exists($this->instance, $method)){
throw new Exception(‘未定义的方法:’ . $method);
}

echo ‘权限检查<br />’;

$callBack = array($this->instance, $method);

$return = call_user_func_array($callBack, $argument);

echo ‘日志记录<br />’;

return $return;
}
}

//工厂方法
class Factory
{
public function getBizInstance(){
return new AOP(new BIZ());
}
}

//客户端调用演示
header(“Content-Type: text/html; charset=utf8”);

try
{
$obj = Factory::getBizInstance();

$obj->foobar();
}
catch(Exception $e)
{
echo ‘Caught exception: ‘, $e->getMessage();
}
[/cce_php]

当然,很优雅的利用php5内置的魔术方法__call来实现AOP,唯一的缺点是要在AOP类里面实例客户端对象,返回的是被AOP包装后的对象,这样在get_class会有一些麻烦!

在看PHP实战的时候发现可以不用在AOP类里面实例客户端对象,但是需要继承一个父类。

部分代码如下,对书上的例子稍作修改。
[cce_php]
//要记录方法调用的父类
class loggingClass{
function __call($method,$args){
if(strchr($method,’Aop_’)){
$method = str_replace(‘Aop_’,”,$method);
if(!method_exists($this,$method)){
throw new Exception(“Call undefinded method “.get_class($this).”::$method”);
}
$log = Log::getInstance();
$log->log(“调用方法”.$method.”之前做点啥”);
$return = call_user_func_array(array($this,$method),$args);
$log->log(“调用方法”.$method.”后再做点啥”);
return $return;
}
}
}

[/cce_php]

利用父类的魔术方法__call实现记录日志操作,当从客户端调用不存在的方法,__call会拦截它,然后就开始记录日志,调用真正的方法,然后日志记录结束。在这个例子中,我修改对方法的判断,只有调用以Aop_为前缀的方法时才会调用__call方法。
[cce_php]

//具体的日志记录类
class Log{
private static $log;
function __construct(){

}
static function getInstance(){
if(self::$log == null){
self::$log = new Log();
}
return self::$log;
}
function log($str){
echo $str.'<br/>’;
}

}

[/cce_php]

实现一个具体的日志类的单一实例的方法

[cce_php]

//带有可记录日子方法的Date类
class Date extends loggingClass{
private $timestamp;
function __construct($timestamp = false){
$this->setinit($timestamp);
}
protected function setinit($timestamp){
$this->timestamp = $timestamp?$timestamp:time();
}
protected function setTime(){
echo ‘业务逻辑<br/>’;
}
}
$date = new Date();
$date->Aop_setTime();
[/cce_php]
具体的业务逻辑类,需要继承loggingClass类,然后就可以开始调用,在这个例子中,客户端是不能调用该类中的setTime方法,因为是protected属性,可修改为public这样客户端进行实例就能调用了。如果有的同学对这样实现起来不是很满意的话,这里有牛人用.net的思想实现的AOP,扩展性很强,当然代码也很多,请看
PHP三层结构(上)——简单三层结构
PHP三层结构(下)——PHP实现AOP

“php的AOP编程实例”的一个回复

发表评论

电子邮件地址不会被公开。 必填项已用*标注