ejsmont-artur/php-proxy-builder

PHP代理构建器 - AOP启发的代理模式库。

0.1.4 2013-03-23 13:45 UTC

This package is not auto-updated.

Last update: 2024-09-14 17:00:46 UTC


README

Build Status

库允许您在任意类实例周围添加代理对象,以在运行时添加行为。

库采用了面向方面编程的概念,其中某些逻辑(如缓存)可以在应用程序中重用,而不必将应用程序代码耦合到缓存实现中。

主要功能

  1. 在运行时创建代理实例。
  2. 代理使用Advice实例(例如CachingAdvice)为代理对象添加行为。
  3. 代理实例将方法调用委派给原始(代理)对象。
  4. 代理、Advice和代理类是完全解耦的。代理不知道它所代理的是什么,也不知道Advice的目的。Advice不关心它是如何被使用的,并且它可以用于任何目标类。最重要的是,客户端代码不需要知道任何代理的存在。它消费代理就像它是目标实例本身一样。代理对客户端是透明的。

示例

<?php
// target instances to be proxied
$target = new SlowService();

// Advice implementing additional logic.
// We will integrate with frameworks to obtain $cacheBackendAdapter from your framework of choice like symfony2.
$advice = new CachingAdvice($cacheBackendAdapter);

$factory = new MagicMethodBasedFactory();
$proxiedService = $factory->createProxy($advice, $target);

// Call is made directly on the object, it's slow.
$target->getSomeData(12345);

// Calls are made through the proxy, which delegates to the CachingAdvice and then to target instance.
// First call is slow, the second call is fast as it is being cached.
$proxiedService->getSomeData(12345);
$proxiedService->getSomeData(12345);

未来实现

现在您可以看到的代码具有完整的测试覆盖率,但它只是库的第一个实现。

当前的实现基于魔术方法。因此,代理既不继承也不扩展代理对象,因此它不会通过类型提示检查或instanceof检查。

在不久的将来,我们将提供第二个实现,它将允许您从任何对象创建一个完全基于接口的代理。这样,代理将完全可互换于目标实例,并且可以通过类型检查

<?php

($proxiedService instanceof SlowService) == true;
($proxiedService instanceof CachingAdvice) == false;

更多示例

请查看单元测试,以了解代码应该如何使用和组装的更多示例。

包含的Advice

通过提供简单而实用的Advice实现,库获得了许多价值。我们决定将所有外部依赖项都排除在库的核心之外,因此我们不需要记录器或缓存实现。我们将与框架集成,在Adapter文件夹中提供我们最小化接口的实现。

  1. CachingAdvice - 为任意对象添加缓存。使用类名、方法名和参数作为缓存键。
  2. CircuitBreakerAdvice - 在对象周围添加断路器,以便在不可用的时候快速失败。
  3. InstrumentationAdvice - 计数方法调用并测量执行时间以进行监控和绘图。
  4. ClosureAdvice - 允许您使用闭包而不是完整的AroundAdviceInterface实现。
  5. LoggingAdvice - 记录所有方法调用以及时间,可选地记录参数/结果。

图表

请见下面的两个序列图,其中想象中的客户端在目标对象上调用“doSomething()”方法。

请注意,Advice对象独立于客户端和目标。它可以被替换和测试,而不需要对客户端或目标代码进行任何更改。

无代理的图表

PHP method call sequence diagram without a proxy

有代理的图表

PHP method call sequence diagram with a proxy object

注释

  1. 代理对象没有以任何方式被修改,它只是被使用。
  2. 您可以代理任何现有的PHP对象。
  3. 被代理的对象可以调用其自身的方法,这些调用不会通过代理进行。这取决于你如何看待它,可以被认为是好事也可以是坏事。如果你想要针对如安全之类的功能选择性地代理方法,这会成为一个问题。你可以想象开发者可能会更改底层代码,将调用从不太安全的方法委托给更安全的方法,而代理将没有机会拦截。另一方面,你可以完全了解发生了什么,并且库非常轻量级,它不会修改现有代码。
  4. 如果你想要严格的AOP(面向切面编程),你可能需要考虑类加载时织入,这在类首次加载时修改类。然后你可以获得完整的方法拦截,因为类创建的实例已经内嵌了代理。查看https://github.com/lisachenko/go-aop-php,它看起来很有希望(不确定是否已准备就绪用于生产环境)。
  5. 性能是一个重要的因素,我们将提供基准测试并确保代码不会减慢整体执行速度。

运行测试

测试是通过PHPUnit运行的,如果你想要运行测试,则假定你已经安装了phpunit。你可以使用ant运行测试,"ci"目标会生成文档和代码覆盖率报告。

你可以使用以下任何命令来运行所有测试

ant
ant phpunit
ant ci

你可以通过运行以下命令来运行选定的测试用例

cd tests
phpunit Unit/PhpProxyBuilder/Aop/ClosureAdviceTest.php

贡献者