mirror of
https://gitee.com/hyperf/hyperf.git
synced 2024-12-04 12:47:55 +08:00
Allow lazy injection through @Inject(lazy=true)
This commit is contained in:
parent
6d31026013
commit
a595c3ae32
@ -32,6 +32,11 @@ class Inject extends AbstractAnnotation
|
||||
*/
|
||||
public $required = true;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
public $lazy = false;
|
||||
|
||||
/**
|
||||
* @var PhpDocReader
|
||||
*/
|
||||
@ -48,6 +53,9 @@ class Inject extends AbstractAnnotation
|
||||
try {
|
||||
$this->value = $this->docReader->getPropertyClass(ReflectionManager::reflectClass($className)->getProperty($target));
|
||||
AnnotationCollector::collectProperty($className, $target, static::class, $this);
|
||||
if ($this->lazy) {
|
||||
$this->value = 'HyperfLazy\\' . $this->value;
|
||||
}
|
||||
} catch (AnnotationException $e) {
|
||||
if ($this->required) {
|
||||
throw $e;
|
||||
|
@ -14,9 +14,12 @@ namespace Hyperf\Di\LazyLoader;
|
||||
|
||||
use Hyperf\Contract\ConfigInterface;
|
||||
use Hyperf\Utils\Coroutine\Locker as CoLocker;
|
||||
use Hyperf\Utils\Str;
|
||||
use PhpParser\NodeTraverser;
|
||||
use PhpParser\NodeVisitor\NameResolver;
|
||||
use PhpParser\ParserFactory;
|
||||
use PhpParser\PrettyPrinter\Standard;
|
||||
use ReflectionClass;
|
||||
|
||||
class LazyLoader
|
||||
{
|
||||
@ -32,7 +35,7 @@ class LazyLoader
|
||||
/**
|
||||
* The singleton instance of the loader.
|
||||
*
|
||||
* @var \Hyperf\Di\LazyLoader\LazyLoader
|
||||
* @var LazyLoader
|
||||
*/
|
||||
protected static $instance;
|
||||
|
||||
@ -51,8 +54,6 @@ class LazyLoader
|
||||
|
||||
/**
|
||||
* Get or create the singleton lazy loader instance.
|
||||
*
|
||||
* @return \Hyperf\Di\LazyLoader\LazyLoader
|
||||
*/
|
||||
public static function bootstrap(ConfigInterface $config): LazyLoader
|
||||
{
|
||||
@ -69,7 +70,7 @@ class LazyLoader
|
||||
*/
|
||||
public function load(string $proxy)
|
||||
{
|
||||
if ($this->config->get($proxy, false)) {
|
||||
if (array_key_exists($proxy, $this->config) || Str::startsWith($proxy, 'HyperfLazy\\')) {
|
||||
$this->loadProxy($proxy);
|
||||
return true;
|
||||
}
|
||||
@ -110,7 +111,7 @@ class LazyLoader
|
||||
$targetPath = $path . '.' . uniqid();
|
||||
$code = $this->generatorLazyProxy(
|
||||
$proxy,
|
||||
$this->config->get($proxy)
|
||||
$this->config[$proxy] ?? Str::after($proxy, 'HyperfLazy\\')
|
||||
);
|
||||
file_put_contents($targetPath, $code);
|
||||
rename($targetPath, $path);
|
||||
@ -124,7 +125,7 @@ class LazyLoader
|
||||
*/
|
||||
protected function generatorLazyProxy(string $proxy, string $target): string
|
||||
{
|
||||
$targetReflection = new \ReflectionClass($target);
|
||||
$targetReflection = new ReflectionClass($target);
|
||||
$fileName = $targetReflection->getFileName();
|
||||
if (! $fileName) {
|
||||
$code = ''; // Classes and Interfaces from PHP internals
|
||||
@ -148,7 +149,7 @@ class LazyLoader
|
||||
*/
|
||||
protected function prependToLoaderStack(): void
|
||||
{
|
||||
/** @var callable(string): void*/
|
||||
/** @var callable(string): void */
|
||||
$load = [$this, 'load'];
|
||||
spl_autoload_register($load, true, true);
|
||||
}
|
||||
@ -159,10 +160,10 @@ class LazyLoader
|
||||
*
|
||||
* TODO: implement some of them.
|
||||
*
|
||||
* @param \ReflectionClass $targetReflection [description]
|
||||
* @param ReflectionClass $targetReflection [description]
|
||||
* @return bool [description]
|
||||
*/
|
||||
private function isUnsupportedReflectionType(\ReflectionClass $targetReflection): bool
|
||||
private function isUnsupportedReflectionType(ReflectionClass $targetReflection): bool
|
||||
{
|
||||
//Final class
|
||||
if ($targetReflection->isFinal()) {
|
||||
@ -199,7 +200,7 @@ class LazyLoader
|
||||
$traverser->addVisitor($visitor);
|
||||
$ast = $traverser->traverse($ast);
|
||||
$builder->addNodes($visitor->nodes);
|
||||
$prettyPrinter = new \PhpParser\PrettyPrinter\Standard();
|
||||
$prettyPrinter = new Standard();
|
||||
$stmts = [$builder->getNode()];
|
||||
return $prettyPrinter->prettyPrintFile($stmts);
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ use PhpParser\Node\Name;
|
||||
use PhpParser\Node\Scalar\MagicConst\Function_ as MagicConstFunction;
|
||||
use PhpParser\Node\Stmt\Class_;
|
||||
use PhpParser\Node\Stmt\ClassMethod;
|
||||
use PhpParser\Node\Stmt\Expression;
|
||||
use PhpParser\Node\Stmt\Return_;
|
||||
use PhpParser\NodeVisitorAbstract;
|
||||
|
||||
@ -36,10 +37,15 @@ class PublicMethodVisitor extends NodeVisitorAbstract
|
||||
{
|
||||
if ($node instanceof ClassMethod) {
|
||||
$methodCall =
|
||||
new Return_(new MethodCall(new Variable('this'), '__call', [
|
||||
new MethodCall(new Variable('this'), '__call', [
|
||||
new Node\Arg(new MagicConstFunction()),
|
||||
new Node\Arg(new FuncCall(new Name('func_get_args'))),
|
||||
]));
|
||||
]);
|
||||
if ($node->returnType && $node->returnType->toString() !== 'void') {
|
||||
$methodCall = new Return_($methodCall);
|
||||
} else {
|
||||
$methodCall = new Expression($methodCall);
|
||||
}
|
||||
$node->stmts = [
|
||||
$methodCall,
|
||||
];
|
||||
|
@ -17,6 +17,7 @@ use Hyperf\Di\LazyLoader\PublicMethodVisitor;
|
||||
use PhpParser\NodeTraverser;
|
||||
use PhpParser\NodeVisitor\NameResolver;
|
||||
use PhpParser\ParserFactory;
|
||||
use PhpParser\PrettyPrinter\Standard;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
@ -63,7 +64,7 @@ class SomeClass extends \App\SomeClass
|
||||
}
|
||||
public function it(\bar\ConfigInterface $a) : void
|
||||
{
|
||||
return $this->__call(__FUNCTION__, func_get_args());
|
||||
$this->__call(__FUNCTION__, func_get_args());
|
||||
}
|
||||
public function works(bool $a, float $b = 1) : int
|
||||
{
|
||||
@ -84,7 +85,7 @@ CODETEMPLATE;
|
||||
$traverser->addVisitor($visitor);
|
||||
$ast = $traverser->traverse($ast);
|
||||
$builder->addNodes($visitor->nodes);
|
||||
$prettyPrinter = new \PhpParser\PrettyPrinter\Standard();
|
||||
$prettyPrinter = new Standard();
|
||||
$stmts = [$builder->getNode()];
|
||||
$newCode = $prettyPrinter->prettyPrintFile($stmts);
|
||||
$this->assertEquals($expected, $newCode);
|
||||
|
@ -17,6 +17,7 @@ use Hyperf\Di\LazyLoader\PublicMethodVisitor;
|
||||
use PhpParser\NodeTraverser;
|
||||
use PhpParser\NodeVisitor\NameResolver;
|
||||
use PhpParser\ParserFactory;
|
||||
use PhpParser\PrettyPrinter\Standard;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
@ -60,7 +61,7 @@ class SomeClass implements \App\SomeInterface
|
||||
}
|
||||
public function it(\bar\ConfigInterface $a) : void
|
||||
{
|
||||
return $this->__call(__FUNCTION__, func_get_args());
|
||||
$this->__call(__FUNCTION__, func_get_args());
|
||||
}
|
||||
public function works(bool $a, float $b = 1) : int
|
||||
{
|
||||
@ -81,7 +82,7 @@ CODETEMPLATE;
|
||||
$traverser->addVisitor($visitor);
|
||||
$ast = $traverser->traverse($ast);
|
||||
$builder->addNodes($visitor->nodes);
|
||||
$prettyPrinter = new \PhpParser\PrettyPrinter\Standard();
|
||||
$prettyPrinter = new Standard();
|
||||
$stmts = [$builder->getNode()];
|
||||
$newCode = $prettyPrinter->prettyPrintFile($stmts);
|
||||
$this->assertEquals($expected, $newCode);
|
||||
|
@ -15,6 +15,7 @@ namespace HyperfTest\Di;
|
||||
use Hyperf\Di\LazyLoader\PublicMethodVisitor;
|
||||
use PhpParser\NodeTraverser;
|
||||
use PhpParser\ParserFactory;
|
||||
use PhpParser\PrettyPrinter\Standard;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
@ -45,7 +46,7 @@ public function hope(bool $a) : int
|
||||
}
|
||||
public function it(ConfigInterface $a) : void
|
||||
{
|
||||
return $this->__call(__FUNCTION__, func_get_args());
|
||||
$this->__call(__FUNCTION__, func_get_args());
|
||||
}
|
||||
public function works(bool $a, float $b = 1) : int
|
||||
{
|
||||
@ -58,7 +59,7 @@ CODETEMPLATE;
|
||||
$visitor = new PublicMethodVisitor();
|
||||
$traverser->addVisitor($visitor);
|
||||
$ast = $traverser->traverse($ast);
|
||||
$prettyPrinter = new \PhpParser\PrettyPrinter\Standard();
|
||||
$prettyPrinter = new Standard();
|
||||
$newCode = $prettyPrinter->prettyPrintFile($visitor->nodes);
|
||||
$this->assertEquals($expected, $newCode);
|
||||
}
|
||||
@ -90,7 +91,7 @@ public function hope(bool $a) : int
|
||||
}
|
||||
public function it(ConfigInterface $a) : void
|
||||
{
|
||||
return $this->__call(__FUNCTION__, func_get_args());
|
||||
$this->__call(__FUNCTION__, func_get_args());
|
||||
}
|
||||
public function works(bool $a, float $b = 1) : int
|
||||
{
|
||||
@ -103,7 +104,7 @@ CODETEMPLATE;
|
||||
$visitor = new PublicMethodVisitor();
|
||||
$traverser->addVisitor($visitor);
|
||||
$ast = $traverser->traverse($ast);
|
||||
$prettyPrinter = new \PhpParser\PrettyPrinter\Standard();
|
||||
$prettyPrinter = new Standard();
|
||||
$newCode = $prettyPrinter->prettyPrintFile($visitor->nodes);
|
||||
$this->assertEquals($expected, $newCode);
|
||||
$this->assertEquals(3, count($visitor->nodes));
|
||||
|
Loading…
Reference in New Issue
Block a user