Added method ProceedingJoinPoint::getInstance() to get instance which will be called by AOP. (#3030)

* Added method `ProceedingJoinPoint::getInstance()` to get instance which was cut by AOP.

* Update CHANGELOG-2.0.md

* Added test cases.
This commit is contained in:
李铭昕 2020-12-26 09:47:58 +08:00 committed by GitHub
parent a6556d80b0
commit 53a3060f49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 91 additions and 11 deletions

View File

@ -1,5 +1,9 @@
# v2.0.25 - TBD
## Added
- [#3030](https://github.com/hyperf/hyperf/pull/3030) Added method `ProceedingJoinPoint::getInstance()` to get instance which will be called by `AOP`.
# v2.0.24 - 2020-12-21
## Fixed
@ -141,7 +145,7 @@
## Optimzied
- [#2347](https://github.com/hyperf/hyperf/pull/2347) You can set `$waitTimeout` for `ConsumerMessage` to stop amqp consumer safely in coroutine style server.
- [#2347](https://github.com/hyperf/hyperf/pull/2347) You can set `$waitTimeout` for `ConsumerMessage` to stop amqp consumer safely in coroutine style server.
# v2.0.17 - 2020-11-02
@ -234,7 +238,7 @@
- [#2565](https://github.com/hyperf/hyperf/pull/2565) Fixed proxy class generate keyword `parent::class` but the class scope has on parent.
- [#2578](https://github.com/hyperf/hyperf/pull/2578) Fixed event `AfterProcessHandle` won't be dispatched when throw exception in process.
- [#2582](https://github.com/hyperf/hyperf/pull/2582) Fixed redis connection has already been bound to another coroutine.
- [#2589](https://github.com/hyperf/hyperf/pull/2589) Fixed amqp consumer does not starts when using coroutine style server.
- [#2589](https://github.com/hyperf/hyperf/pull/2589) Fixed amqp consumer does not starts when using coroutine style server.
- [#2590](https://github.com/hyperf/hyperf/pull/2590) Fixed crontab does not works when using coroutine style server.
## Optimized
@ -465,7 +469,7 @@
## Optimized
- [#2049](https://github.com/hyperf/hyperf/pull/2049) Optimized stdout when server restart for `hyperf/watcher`.
- [#2090](https://github.com/hyperf/hyperf/pull/2090) Adapte original response object for `hyperf/session`.
- [#2090](https://github.com/hyperf/hyperf/pull/2090) Adapte original response object for `hyperf/session`.
## Changed
@ -487,7 +491,7 @@
## Fixed
- [#1952](https://github.com/hyperf/hyperf/pull/1952) Fixed bug that migration will be created although class already exists.
- [#1960](https://github.com/hyperf/hyperf/pull/1960) Fixed `Hyperf\HttpServer\ResponseEmitter::isMethodsExists()` method does not works as expected.
- [#1960](https://github.com/hyperf/hyperf/pull/1960) Fixed `Hyperf\HttpServer\ResponseEmitter::isMethodsExists()` method does not works as expected.
- [#1961](https://github.com/hyperf/hyperf/pull/1961) Fixed start failed when `config/autoload/aspects.php` does not exists.
- [#1964](https://github.com/hyperf/hyperf/pull/1964) Fixed http status code 500 caused by empty body.
- [#1965](https://github.com/hyperf/hyperf/pull/1965) Fixed the wrong http code when `initRequestAndResponse` failed.
@ -510,7 +514,7 @@
## Major Changes
1. Refactor [hyperf/di](https://github.com/hyperf/di) component, in particular, AOP and Annotation Scanner are optimized, in v2.0, the component use a brand new loading mechanism to provided an incredible AOP function.
1. Refactor [hyperf/di](https://github.com/hyperf/di) component, in particular, AOP and Annotation Scanner are optimized, in v2.0, the component use a brand new loading mechanism to provided an incredible AOP function.
1. The most significant functional differences compared to v1.x is that you can cut into any classes in any ways with Aspect. For example, in v1.x, you can only use AOP in the class instance that created by Hyperf DI container, you cannot cut into the class instance that created by `new` identifier. But now, in v2.0, it is available. But there is still has an exception, the classes that used in bootstrap stage still cannot works.
2. In v1.x, the AOP ONLY available for the normal classes, not for Final class that cannot be inherited by a subclass. But now, in v2.0. it is available.
3. In v1.x, you cannot use the property value that marked by `@Inject` or `@Value` annotation in the constructor of current class. But now, in v2.0, it is available.
@ -520,9 +524,9 @@
7. In v1.x, the proxy class will not re-generate when the proxy file exists even the code of the proxy class changed, this strategy will improve the time-consuming of scan, but at the same time, this will lead to a certain degree of development inconvenience. And now, in v2.0, the file cache of proxy class will generated according to the code content of the proxy class, this changes will reduces the mental burden of development.
8. Add `priority` parameter for Aspect, now you could define `priority` in Aspect class by class property or annotation property, to manage the order of the aspects.
9. In v1.x, you can only define an Aspect class by `@Aspect` annotation, you cannot define the Aspect class by configuration file. But now, in v2.0, it is available to define the Aspect class by configuration file or ConfigProvider.
10. In v1.x, you have to add `Hyperf\Di\Listener\LazyLoaderBootApplicationListener` to enable lazy loading. In 2.0, lazy loading can be used directly. This listener is therefore removed.
10. In v1.x, you have to add `Hyperf\Di\Listener\LazyLoaderBootApplicationListener` to enable lazy loading. In 2.0, lazy loading can be used directly. This listener is therefore removed.
11. Added `annotations.scan.class_map` configuration, now you could replace any content of class dynamically above the autoload rules.
## Dependencies Upgrade
- Upgraded `ext-swoole` to `>=4.5`;
@ -561,7 +565,7 @@
- Process mode of config-center, crontab, metric, comsumers of MQ can not running in coroutine server.
- Change the life-cycle of `Hyperf\AsyncQueue\Environment`, can only applies in the current coroutine, not the whole current process.
- Coroutine Server does not support task mechanism.
- [#1877](https://github.com/hyperf/hyperf/pull/1877) Support to use typehint of property on PHP 8 to replace `@var` when using `@Inject` annotation, for example:
```

View File

@ -108,4 +108,11 @@ class ProceedingJoinPoint
$this->methodName
);
}
public function getInstance(): ?object
{
$ref = new \ReflectionFunction($this->originalMethod);
return $ref->getClosureThis();
}
}

View File

@ -14,6 +14,7 @@ namespace HyperfTest\Di;
use Hyperf\Di\Annotation\AnnotationCollector;
use Hyperf\Di\Annotation\AspectCollector;
use Hyperf\Utils\ApplicationContext;
use HyperfTest\Di\Stub\Aspect\GetNameAspect;
use HyperfTest\Di\Stub\Aspect\IncrAspect;
use HyperfTest\Di\Stub\Aspect\IncrAspectAnnotation;
use HyperfTest\Di\Stub\ProxyTraitObject;
@ -47,6 +48,29 @@ class ProxyTraitTest extends TestCase
$this->assertEquals(['id', 'str', 'num'], $obj->get3(1, 'hy')['order']);
}
public function testProceedingJoinPointGetInstance()
{
$aspect = [];
ApplicationContext::setContainer(value(function () use (&$aspect) {
$container = Mockery::mock(ContainerInterface::class);
$container->shouldReceive('get')->with(Mockery::any())->andReturnUsing(function ($class) use (&$aspect) {
$aspect[] = $class;
return new $class();
});
return $container;
}));
$obj = new ProxyTraitObject();
$this->assertSame('HyperfCloud', $obj->getName2());
AspectCollector::set('classes', [
GetNameAspect::class => [ProxyTraitObject::class],
]);
$obj = new ProxyTraitObject();
$this->assertSame('Hyperf', $obj->getName());
}
public function testHandleAround()
{
$aspect = [];

View File

@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
/**
* This file is part of Hyperf.
*
* @link https://www.hyperf.io
* @document https://hyperf.wiki
* @contact group@hyperf.io
* @license https://github.com/hyperf/hyperf/blob/master/LICENSE
*/
namespace HyperfTest\Di\Stub\Aspect;
use Hyperf\Di\Aop\AbstractAspect;
use Hyperf\Di\Aop\ProceedingJoinPoint;
class GetNameAspect extends AbstractAspect
{
public function process(ProceedingJoinPoint $proceedingJoinPoint)
{
return $proceedingJoinPoint->getInstance()->name;
}
}

View File

@ -17,6 +17,16 @@ class ProxyTraitObject
{
use ProxyTrait;
/**
* @var string
*/
public $name;
public function __construct(string $name = 'Hyperf')
{
$this->name = $name;
}
public function get(?int $id, string $str = '')
{
return $this->__getParamsMap(static::class, 'get', func_get_args());
@ -34,10 +44,22 @@ class ProxyTraitObject
public function incr()
{
$__function__ = __FUNCTION__;
$__method__ = __METHOD__;
return self::__proxyCall(ProxyTraitObject::class, __FUNCTION__, self::__getParamsMap(ProxyTraitObject::class, __FUNCTION__, func_get_args()), function () use ($__function__, $__method__) {
return self::__proxyCall(ProxyTraitObject::class, __FUNCTION__, self::__getParamsMap(ProxyTraitObject::class, __FUNCTION__, func_get_args()), function () {
return 1;
});
}
public function getName()
{
return self::__proxyCall(ProxyTraitObject::class, __FUNCTION__, self::__getParamsMap(ProxyTraitObject::class, __FUNCTION__, func_get_args()), function () {
return 'HyperfCloud';
});
}
public function getName2()
{
return self::__proxyCall(ProxyTraitObject::class, __FUNCTION__, self::__getParamsMap(ProxyTraitObject::class, __FUNCTION__, func_get_args()), function () {
return 'HyperfCloud';
});
}
}