php的AOP编程实例

目录

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

下面是实例代码


//应用程序中某个业务逻辑类

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();

}

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

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

部分代码如下,对书上的例子稍作修改。


//要记录方法调用的父类

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;

}

}

}

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

//具体的日志记录类

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/>';

}

}

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


//带有可记录日子方法的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();

具体的业务逻辑类,需要继承loggingClass类,然后就可以开始调用,在这个例子中,客户端是不能调用该类中的setTime方法,因为是protected属性,可修改为public这样客户端进行实例就能调用了。如果有的同学对这样实现起来不是很满意的话,这里有牛人用.net的思想实现的AOP,扩展性很强,当然代码也很多,请看

PHP三层结构(上)——简单三层结构

PHP三层结构(下)——PHP实现AOP