在 PHP 中近似实现 AOP 思想

发布于 2023-06-13 22:32:08 字数 2967 浏览 42 评论 0

AOP 为 Aspect Oriented Programming 的缩写,意为: 面向切面编程 ,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

主要的功能 是:日志记录,性能统计,安全控制,事务处理,异常处理等等。

主要的意图 是:将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。

PHP 实现

PHP 的原生内核并没有相关的实现,不过借助魔术函数可以近似实现。

下面的代码主要实现了对实现了对业务类的包装:

  • 定义了两个层次的前置和后置函数:可以全局的(类层面的所有 action),也可以局部的(对某个 action 的)
  • 允许继承

代码如下:

/** 
 * 业务逻辑类的包装类
 *
 * 执行顺序:
 * 1. 全局前置函数
 * 2. 局部前置函数
 * 3. 业务逻辑
 * 4. 局部后置函数
 * 5. 全局后置函数
 *
 * @author cyy0523xc@gmail.com
 */
final class AOP
{
    private $instance;

    // 全局的前置函数和后置函数
    // 每个action调用时都会调用
    // @todo 可以在配置文件配置
    const GLOBAL_BEFORE_FUNC = '_before';
    const GLOBAL_AFTER_FUNC  = '_after';

    // 特定action的前置函数和后置函数的前缀
    const LOCAL_BEFORE_PRE   = '_before_';
    const LOCAL_AFTER_PRE    = '_after_';

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

    public function __call($method, $params)
    {
        if (!$this->__hasMethod($method)) {
            throw new Exception("Call undefinded method " . get_class($this->instance) . "::$method");
        }

        // 调用全局前置函数
        if ($this->__hasMethod(AOP::GLOBAL_BEFORE_FUNC)) {
            $this->__callMethod(AOP::GLOBAL_BEFORE_FUNC);
        }

        // 调用前置函数
        if ($this->__hasMethod(AOP::LOCAL_BEFORE_PRE . $method)) {
            $this->__callMethod(AOP::LOCAL_BEFORE_PRE . $method);
        }

        // 调用业务函数
        $return = $this->__callMethod($method, $params);

        // 调用局部后置函数
        if ($this->__hasMethod(AOP::LOCAL_AFTER_PRE . $method)) {
            $this->__callMethod(AOP::LOCAL_AFTER_PRE . $method);
        }

        // 调用全局后置函数
        if ($this->__hasMethod(AOP::GLOBAL_AFTER_FUNC)) {
            $this->__callMethod(AOP::GLOBAL_AFTER_FUNC);
        }

        return $return;
    }

    /**
     * 判断方法是否存在
     * 使用双下划线前缀主要是为了避免冲突
     * @param string $method 方法名
     * @return mixed
     */
    private function __hasMethod($method)
    {
        return method_exists($this->instance, $method);
    }

    /**
     * 调用方法
     * @param string $method 方法名
     * @param array  $params 参数数组
     * @return mixed
     */
    private function __callMethod($method, array $params = null)
    {
        $callBack = array(
            $this->instance,
            $method
        );

        if (null === $params) {
            return call_user_func($callBack);
        } else {
            return call_user_func_array($callBack, $params);
        }
    }
}

源码文件:

wget https://github.com/cyy0523xc/code/raw/master/php/test/aop.php -O aop.php

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

跨年

暂无简介

文章
评论
27 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文