goaop/goaop-laravel-bridge

Go! AOP 框架的集成桥梁

1.1.1 2020-10-07 09:59 UTC

README

Scrutinizer Code Quality GitHub release Minimum PHP Version License

GoAopBridge 为 Laravel5 应用程序添加了通过 Go! AOP 框架进行面向切面编程的支持。

概述

面向切面范式允许使用特殊工具扩展标准面向对象范式,以有效解决应用程序中的横切关注点。此类代码通常存在于应用程序的各个地方(例如,日志记录、缓存、监控等),没有 AOP 就很难解决这个问题。

AOP 为开发者定义了新的工具,它们是

  • 连接点 - 代码中的位置,可用于拦截,例如,单个公共方法的执行或单个对象属性的访问。
  • 切点是使用特殊正则表达式表达式定义的连接点列表,用于源代码,例如,具体类或命名空间中的所有公共和受保护方法。
  • 通知是一个在具体连接点之前、之后或周围调用的附加回调。对于 PHP,每个通知都表示为一个 \Closure 实例,它被包装在拦截器对象中。
  • 切面是一个特殊类,它将切点和通知结合起来,每个切点都定义为注解,每个通知都是该切面内部的方法。

您可以在不同来源中了解更多关于 AOP 的信息,有关 Java 语言的优秀文章也可以应用于 PHP,因为它是一个通用范式。或者,您可以观看一个关于 Laravel 中的 AOP 的很好的演示

安装

可以使用 composer 轻松安装 GoAopBridge。只需运行以下命令请求 composer 下载包含依赖项的包

$ composer require goaop/goaop-laravel-bridge

Laravel 5.5+

无需操作。在执行 composer require goaop/goaop-laravel-bridge 命令后,包将自动安装和配置。如果要手动配置,请按照以下步骤操作

Laravel 5.4 或更早版本

Go\Laravel\GoAopBridge\GoAopServiceProvider 添加到 config/app.php 的 providers 数组中

// config/app.php

    'providers' => [
        // Go! Aspect Service Provider
        Go\Laravel\GoAopBridge\GoAopServiceProvider::class,

请确保此服务提供程序是此列表中的 第一项。这是 AOP 引擎正常工作的要求。

Lumen

在您的 bootstrap/app.php 中将 Go\Laravel\GoAopBridge\GoAopServiceProvider 注册到应用程序中

// bootstrap/app.php
<?php
// After `$app` is created

$app->register(\Go\Laravel\GoAopBridge\GoAopServiceProvider::class);

请确保这是对 $app->register()第一次调用。这是 AOP 引擎正常工作的要求。

配置

config/go_aop.php 文件中的默认配置。如果您想更改任何默认值,您必须将此文件复制到自己的配置目录中以修改值。

如果您使用 Laravel,您可以使用此命令发布配置

./artisan vendor:publish --provider="Go\Laravel\GoAopBridge\GoAopServiceProvider"

如果您使用 Lumen,您必须手动加载配置文件,例如

// bootstrap/app.php
<?php
// After `$app` is created

$app->configure('go_aop');

配置可用于对 AOP 内核和源代码的 whitelisting/blacklisting 进行额外的调整。

// config/go_aop.php

return [
    /*
     |--------------------------------------------------------------------------
     | AOP Debug Mode
     |--------------------------------------------------------------------------
     |
     | When AOP is in debug mode, then breakpoints in the original source code
     | will work. Also engine will refresh cache files if the original files were
     | changed.
     | For production mode, no extra filemtime checks and better integration with opcache
     |
     */
    'debug' => env('APP_DEBUG', false),

    /*
     |--------------------------------------------------------------------------
     | Application root directory
     |--------------------------------------------------------------------------
     |
     | AOP will be applied only to the files in this directory, change it to app_path()
     | if needed
     */
    'appDir' => base_path(),

    /*
     |--------------------------------------------------------------------------
     | AOP cache directory
     |--------------------------------------------------------------------------
     |
     | AOP engine will put all transformed files and caches in that directory
     */
    'cacheDir' => storage_path('app/aspect'),

    /*
     |--------------------------------------------------------------------------
     | Cache file mode
     |--------------------------------------------------------------------------
     |
     | If configured then will be used as cache file mode for chmod.
     | WARNING! Use only integers here, not a string, e.g. 0770 instead of '0770'
     */
    'cacheFileMode' => null,

    /*
     |--------------------------------------------------------------------------
     | Controls miscellaneous features of AOP engine
     |--------------------------------------------------------------------------
     |
     | See \Go\Aop\Features enumeration for bit mask
     */
    'features' => 0,

    /*
     |--------------------------------------------------------------------------
     | White list of directories
     |--------------------------------------------------------------------------
     |
     | AOP will check this list to apply an AOP to selected directories only,
     | leave it empty if you want AOP to be applied to all files in the appDir
     */
    'includePaths' => [
        app('path')
    ],

    /*
     |--------------------------------------------------------------------------
     | Black list of directories
     |--------------------------------------------------------------------------
     |
     | AOP will check this list to disable AOP for selected directories
     */
    'excludePaths' => [],

    /*
     |--------------------------------------------------------------------------
     | AOP container class
     |--------------------------------------------------------------------------
     |
     | This option can be useful for extension and fine-tuning of services
     */
    'containerClass' => GoAspectContainer::class,
]

定义新的切面

切面是 Laravel 应用程序中的服务,通过服务提供程序加载到 AOP 容器中,该服务提供程序收集容器中带有 goaop.aspect 标记的所有服务。以下是一个如何实现日志切面的示例,该切面将在 app/ 目录中记录公共方法调用的信息。

方面类的定义,包含pointuct和日志建议

<?php

namespace App\Aspect;

use Go\Aop\Aspect;
use Go\Aop\Intercept\MethodInvocation;
use Go\Lang\Annotation\Before;
use Psr\Log\LoggerInterface;

/**
 * Application logging aspect
 */
class LoggingAspect implements Aspect
{
    /**
     * @var LoggerInterface
     */
    private $logger;

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

    /**
     * Writes a log info before method execution
     *
     * @param MethodInvocation $invocation
     * @Before("execution(public **->*(*))")
     */
    public function beforeMethod(MethodInvocation $invocation)
    {
        $this->logger->info($invocation, $invocation->getArguments());
    }
}

为了在容器中注册所有应用程序方面,创建一个服务提供者(或使用现有的一个)

./artisan make:provider AopServiceProvider

在这个服务提供者的register()方法内部,添加方面的声明,并用goaop.aspect标签标记

namespace App\Providers;

use App\Aspect\LoggingAspect;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\ServiceProvider;
use Psr\Log\LoggerInterface;

class AopServiceProvider extends ServiceProvider
{

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton(LoggingAspect::class, function (Application $app) {
            return new LoggingAspect($app->make(LoggerInterface::class));
        });

        $this->app->tag([LoggingAspect::class], 'goaop.aspect');
    }

别忘了将此服务提供者添加到你的config/app.php服务提供者列表中!

许可证

此桥接器采用MIT许可证。请参阅根目录中的完整LICENSE文件