goaop / goaop-symfony-bundle
Go! AOP 框架的集成桥梁
Requires
- goaop/framework: ^2.1.2
- symfony/console: ^2.6|^3.0|^4.0
- symfony/framework-bundle: ^2.6|^3.0|^4.0|^5.0
Requires (Dev)
- doctrine/orm: ^2.5
- matthiasnoback/symfony-dependency-injection-test: ^1.1.0
- phpunit/phpunit: ^5.7
- roave/security-advisories: dev-master
- symfony/debug: ^2.7|^3.0|^4.0
- symfony/expression-language: ^3.3|^4.0
- symfony/filesystem: ^2.8|^3.0|^4.0
- symfony/phpunit-bridge: ^3.3.4|^4.0
- symfony/process: ^3.3|^4.0
README
GoAopBundle 为 Symfony2 应用程序添加了通过 Go! AOP 框架进行面向切面编程的支持。 不支持 Symfony 3.4 及以上版本! 需要对包进行全局重写才能使其适用于 Symfony 的新版本。
概述
面向切面范式允许使用特殊工具扩展标准面向对象范式,以有效地解决应用程序中的横切关注点。此类代码通常存在于应用程序的各个地方(例如,日志记录、缓存、监控等),而没有 AOP 就难以修复这些问题。
AOP 为开发者定义了新的工具,包括
- 连接点 - 代码中可用于拦截的位置,例如执行单个公共方法或访问单个对象属性。
- 切入点是一组使用特殊正则表达式表达式定义的连接点列表,用于源代码,例如,具体类或命名空间中的所有公共和受保护方法。
- 通知是在具体连接点之前、之后或周围调用的附加回调。对于 PHP,每个通知都表示为一个
\Closure
实例,包装在拦截器对象中。 - 切面是结合点切面和通知的特殊类,每个切入点都定义为注解,每个通知都是此切面中的方法。
您可以在不同来源中了解更多有关 AOP 的信息,关于 Java 语言的良好文章也适用于 PHP,因为这是一个通用范式。
安装
可以使用 composer 容易地安装 GoAopBundle。只需运行以下命令让 composer 下载包含依赖项的包
$ composer require goaop/goaop-symfony-bundle
版本 1.x 适用于 Symfony >=2.0 <2.7,版本 2.x(master)适用于 Symfony >= 2.7 和 3.x
然后请确保在内核中启用了该包
// app/AppKernel.php public function registerBundles() { $bundles = array( new Go\Symfony\GoAopBundle\GoAopBundle(), // ... ); }
请确保该包是列表中的第一个项目。这是 AOP 引擎正确工作所必需的。
配置
需要为 AOP 内核和源代码的白名单/黑名单提供额外的调整配置包。
# app/config/config.yml go_aop: # This setting enables or disables an automatic AOP cache warming in the application. # By default, cache_warmer is enabled (true), disable it only if you have serious issues with # cache warming process. cache_warmer: true # This setting enables or disables workaround for weaving of Doctrine ORM entities. By default, # it is disabled. If you are using Doctrine ORM and you are using AOP to weave Doctrine entities, # enable this feature. For details about this known issue, see https://github.com/goaop/framework/issues/327 doctrine_support: false # Additional settings for the Go! AOP kernel initialization options: # Debug mode for the AOP, enable it for debugging and switch off for production mode to have a # better runtime performance for your application debug: %kernel.debug% # Application root directory, AOP will be applied ONLY to the files in this directory, by default it's # src/ directory of your application. app_dir: "%kernel.root_dir%/../src" # AOP cache directory where all transformed files will be stored. cache_dir: %kernel.cache_dir%/aspect # Whitelist is array of directories where AOP should be enabled, leave it empty to process all files include_paths: [] # Exclude list is array of directories where AOP should NOT be enabled, leave it empty to process all files exclude_paths: [] # AOP container class name can be used for extending AOP engine or services adjustment container_class: ~ # List of enabled features for AOP kernel, this allows to enable function interception, support for # read-only file systems, etc. Each item should be a name of constant from the `Go\Aop\Features` class. features: []
此包也支持 XML 格式配置,有关 XML 格式,请使用提供的 XML 架构文件。
定义新的切面
切面是 Symfony2 应用程序中的服务,并通过带有 goaop.aspect
标签的服务编译器收集所有服务加载到 AOP 容器中。以下是如何实现一个在 src/ 目录中记录公共方法调用的日志切面的示例。
定义具有切入点和日志通知的切面类
<?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()); } }
在容器中注册切面
services: logging.aspect: class: App\Aspect\LoggingAspect arguments: ["@logger"] tags: - { name: goaop.aspect }
如果您正在使用带有自动注入和自动配置服务的 Symfony 3.3+,则您的切面将自动注册。
已知问题和解决方案
- 默认情况下,如果不进行额外配置,无法编织 Doctrine ORM 实体(参见 goaop/framework#327)。然而,此捆绑包提供了可以轻松在配置中启用的解决方案(参见上文中的配置部分)。默认情况下禁用解决方案是为了提高性能。
- 当注册一个依赖使用编织类的服务或依赖使用编织类的服务的方面时,可能会遇到循环引用问题。目前,此类场景的检测尚未实现,但是有两种解决方案:
- 您可以在方面中注入服务容器或服务定位器,而不是注入编织的服务(参见 https://symfony.ac.cn/doc/master/service_container/service_locators.html)。
- 您可以将编织服务定义为“懒加载”,这将注入其懒加载代理(参见 https://symfony.ac.cn/doc/current/service_container/lazy_services.html)。
许可证
此捆绑包采用 MIT 许可证。请参阅捆绑包中的完整许可证。
Resources/meta/LICENSE