AOP(Abstract Oriented Programming),面向切面编程。AOP是OOP的补充和完善,OOP通过封装继承多态建立一种从上到下的系统层次,但对于与系统业务逻辑无关,每一层次都涉及的功能却无能为力,例如日志。这种分散到各处的被称为横切cross-cutting。
切面(Aspect):
一个关注点的模块化,这个关注点横切多个对象。例如logging,caching,transaction
连接点(Joinpoint):
程序执行过程中明确的点,如方法的调用,特定的异常被抛出或属性的获取。
通知(Advice):
切面在特定连接点采取的行动。
切入点(Pointcut):
指定一个通知将被引发的一系列连接点的集合
。
引入(Introduction):
添加方法或字段到被通知的类。
织入(Weaving):
组装切面来创建一个被通知对象。这可以在编译时或加载时完成,也可以在运行时完成。
PHP魔术方法实现伪PHP。
代码执行未定义的方法时会调用__call方法,通过重定义__callf方法以实现AOP。
class log {
function __call($method,$args) {
$method = "_$method";
echo 'log begins...
';
$return = call_user_func_array(array($this, $method), $args);
echo 'log ends...
';
return $return;
}
}
class user extends log {
function _show() {
echo 'This is show.
';
}
}
$news = new user();
$news->show();
//运行结果:
//log begins...
//This is show.
//log ends...
也可以改进这种方法,将AOP实现部分进行包装,添加配置信息字段。使实现类不用继承父类的call方法。
AOP的实现可以通过读取类,将类解包,添加需要的操作,将类重新打包成新类调用。
创建需要监听的类。当调用user中方法时候实现监听,记录log。
class user{
public function show(){
echo 'User SHOW.
';
}
}
创建配置信息和wrap类,wrap实现aop部分功能。
//配置信息
$wrappers = array(
'user'=>array(
'class'=>'userWrapper'
)
);
class Wrapper{
private $source;
public function __construct($source){
$this->source = $source;
}
public function __call($name,$para){
$this->before($name,$para);
if (method_exists($this->source, $name)){
$return = call_user_func_array(array($this->source,$name), $para);
}
$this->after($name,$para);
return $return;
}
//将类进行包装
public static function wrap($source){
$wrapperConfig = $GLOBALS['wrappers'][get_class($source)];
if ($wrapperConfig){
$wrapperClass = $wrapperConfig['class'];
$wrapper = new $wrapperClass($source);
}
return $wrapper?$wrapper:$source;
}
}
class userWrapper extends Wrapper{
public function before($name,$para){
echo 'Logging begins...
';
}
public function after(){
echo 'Logging ends...
';
}
}
//测试
$user = Wrapper::wrap(new user());
$user->show();
//测试结果:
//Logging begins...
//User SHOW.
//Logging ends...
这种方法虽然实现了aop的部分功能。但对代码存在污染,并未做到真正的切面剥离。