PHP AOP面向切面编程

AOP:Aspect Oriented Programming(面向切面编程)

字面解析:这里的切面(Aspect) 通常是指类的一个实例方法,也就是说其实我们只要在类的一个实例方法执行前或后面挂载前置或后置方法,有点像钩子,其实目的都是一样的,都是为了切分和扩展相应方法的功能,而不需要在原始方法里面改动。

题外话:什么是实例方法?就是类的方法前面没有 static 关键字修饰,并且只有类的实例被创建(new)出来之后才可以使用的方法。

实例1:模拟数据库的建立连接前后的动作

<?php

namespace Mysql;

class Database {

public function beforeConnect($connStr)
{
echo "before connectn";
}

public function afterConnect($connStr)
{
echo "after connectn";
}

public function connect($connStr)
{
$beforeMethod = "before".ucfirst(__FUNCTION__);
$args = func_get_args();
if(method_exists($this,$beforeMethod)){
call_user_func_array([$this,$beforeMethod], $args);
}
// todo: connect the database

echo "connectingn";
$afterMethod = "after".ucfirst(__FUNCTION__);
if(method_exists($this,$afterMethod)){
call_user_func_array([$this,$afterMethod], $args);
}
}

}

$db = new Database();
$db->connect("...");

运行结果如下:

before connect

connecting

after connect

实例2:安装PECL C扩展,PHP AOP,仅支持PHP5.5

项目地址:https://github.com/AOP-PHP/AOP (可直接看源码)

假定有下面的类:

<?php

class MyServices
{

public function doAdminStuff1 ()
{
//some stuff only the admin should do
echo "Calling doAdminStuff1";
}

public function doAdminStuff2 ()
{
//some stuff only the admin should do
echo "Calling doAdminStuff2";
}

}

我们接下来注入关注面:

aop_add_before('MyServices->doAdmin*()', 'adviceForDoAdmin');

其中adviceForDoAdmin:

function adviceForDoAdmin ()
{
if ((! isset($_SESSION['user_type'])) || ($_SESSION['user_type'] !== 'admin')) {
throw new Exception('Sorry, you should be an admin to do this');
}
}

其实上面的代码作用很简单,就是当我们调用 MyServices 类下面的 doAdmin 开头的实例方法前先执行一遍 adviceForDoAdmin 方法,这个 C 扩展是不是挺神奇的。

其实,phper平时写业务代码比较多,较少接触到AOP相关的概念,若你看过某些开源框架的源码或者自己设计过需要AOP切分的业务逻辑那就另当别论了。然而Java里面包含了很多AOP的经典设计范例,比较知名的如Spring AOP。

补充说明:

关于AOP
AOP的实现,一种横向抽取机制,依赖于动态代理模式。
关于AOP的几个重点概念:
JoinPoint:连接点,说白了,就是可以被增强的方法;
PointCut:切入点,对哪些JoinPoint进行拦截;
Advice:通知,就是拦截后的动作;
Aspect:切面,把增强应用到具体方法的过程;
Spring的AOP需要借助aspectj来实现,可以通过XML,也可以通过注解来完成。
比如,采用XML方式的话,需要指明用A类的哪个方法对B类的哪些方法上进行增强,这里就涉及到execution表达式了;
比如,采用注解方式的话,就更加简单了,先在XML中开启AOP(),然后在增强方法上直接使用类似@Before(value=”execution(具体的表达式)”)即可;
其实,在实际开发中,我们对于AOP最常用的就是事务了。

转载请注明出处:https://www.onexin.net/php-aop/

相关文章:

1、PHP之AOP面向切面编程(勾子与行为)
https://www.onexin.net/php-aop-2/

2、用 PHP 编写更好的正则表达式regex
https://www.onexin.net/php-regex/

3、PHP 版本 8.2,8.1,8.0,7.4
https://www.onexin.net/php-8_2-8_1-8_0-7_4/

4、PHP中的Liskov替换原则
https://www.onexin.net/php-liskov/

5、php实现自运行的do实例详解
https://www.onexin.net/php-do/

Leave a Reply