Skip to content

Commit e1f68c0

Browse files
committed
fix: swoft-cloud/swoft/issues/1246 optimize proxy class generate logic
1 parent bac7277 commit e1f68c0

8 files changed

Lines changed: 70 additions & 52 deletions

File tree

src/proxy/src/Ast/Parser.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
<?php declare(strict_types=1);
22

3-
43
namespace Swoft\Proxy\Ast;
54

65
use Exception;
7-
use function file_exists;
8-
use function file_get_contents;
96
use PhpParser\ErrorHandler;
107
use PhpParser\Lexer;
118
use PhpParser\NodeTraverser;
@@ -14,6 +11,8 @@
1411
use PhpParser\PrettyPrinter\Standard;
1512
use Swoft\Proxy\Exception\ProxyException;
1613
use Swoft\Stdlib\Helper\ComposerHelper;
14+
use function file_exists;
15+
use function file_get_contents;
1716

1817
/**
1918
* Class Parser
@@ -126,4 +125,4 @@ private function getCodeByClassName(string $className): string
126125

127126
return file_get_contents($file);
128127
}
129-
}
128+
}
Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
<?php declare(strict_types=1);
22

3-
43
namespace Swoft\Proxy\Ast\Visitor;
54

6-
75
use PhpParser\NodeVisitorAbstract;
86
use Swoft\Proxy\Contract\VisitorInterface;
97

8+
/**
9+
* Class Visitor
10+
*
11+
* @package Swoft\Proxy\Ast\Visitor
12+
*/
1013
abstract class Visitor extends NodeVisitorAbstract implements VisitorInterface
1114
{
1215

13-
}
16+
}

src/proxy/src/Contract/VisitorInterface.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
<?php declare(strict_types=1);
22

3-
43
namespace Swoft\Proxy\Contract;
54

65
/**
@@ -19,4 +18,4 @@ public function getProxyName(): string;
1918
* @return string
2019
*/
2120
public function getProxyClassName(): string;
22-
}
21+
}

src/proxy/src/Proxy.php

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,30 @@
11
<?php declare(strict_types=1);
22

3-
43
namespace Swoft\Proxy;
54

6-
7-
use function file_put_contents;
8-
use const PHP_EOL;
9-
use function sprintf;
105
use Swoft\Proxy\Ast\Parser;
116
use Swoft\Proxy\Ast\Visitor\Visitor;
12-
use Swoft\Proxy\Contract\VisitorInterface;
137
use Swoft\Proxy\Exception\ProxyException;
148
use Swoft\Stdlib\Helper\Sys;
9+
use function file_put_contents;
10+
use function sprintf;
11+
use const PHP_EOL;
1512

13+
/**
14+
* Class Proxy
15+
*
16+
* @package Swoft\Proxy
17+
*/
1618
class Proxy
1719
{
20+
/**
21+
* Optimize logic
22+
* - Save classes that have been parsed and generated to avoid repeated parsing and loading
23+
*
24+
* @var array
25+
*/
26+
private static $caches = [];
27+
1828
/**
1929
* New class name by proxy
2030
*
@@ -26,19 +36,17 @@ class Proxy
2636
*/
2737
public static function newClassName(string $className, Visitor $visitor): string
2838
{
29-
$parser = new Parser();
30-
31-
$visitorClassName = get_class($visitor);
32-
if (!$visitor instanceof VisitorInterface) {
33-
throw new ProxyException(
34-
sprintf('%s is not instance of %s', $visitorClassName, VisitorInterface::class)
35-
);
39+
if (isset(self::$caches[$className])) {
40+
return self::$caches[$className];
3641
}
3742

38-
$parser->addNodeVisitor($visitorClassName, $visitor);
43+
$parser = new Parser();
44+
$parser->addNodeVisitor(get_class($visitor), $visitor);
3945

4046
$proxyCode = $parser->parse($className);
4147
$proxyName = $visitor->getProxyName();
48+
// New proxy class name
49+
$newClassName = $visitor->getProxyClassName();
4250

4351
// Proxy file and proxy code
4452
$proxyFile = sprintf('%s/%s.php', Sys::getTempDir(), $proxyName);
@@ -50,18 +58,28 @@ public static function newClassName(string $className, Visitor $visitor): string
5058
throw new ProxyException(sprintf('Proxy file(%s) generate fail', $proxyFile));
5159
}
5260

53-
// Load proxy php file
61+
// Load new proxy class file.
62+
self::loadProxyClass($proxyFile);
63+
64+
// Ensure proxy class is loaded
65+
if (!class_exists($newClassName)) {
66+
throw new ProxyException(sprintf('Proxy class(%s) is not exist!', $newClassName));
67+
}
68+
69+
// Add cache, mark has been required.
70+
self::$caches[$className] = $newClassName;
71+
return $newClassName;
72+
}
73+
74+
/**
75+
* @param string $proxyFile
76+
*/
77+
private static function loadProxyClass(string $proxyFile): void
78+
{
79+
/** @noinspection PhpIncludeInspection */
5480
require $proxyFile;
5581

5682
// Remove proxy file
5783
unlink($proxyFile);
58-
59-
// Proxy class
60-
$proxyClassName = $visitor->getProxyClassName();
61-
if (!class_exists($proxyClassName)) {
62-
throw new ProxyException(sprintf('Proxy class(%s) is not exist!', $proxyClassName));
63-
}
64-
65-
return $proxyClassName;
6684
}
67-
}
85+
}

src/proxy/test/unit/ProxyTest.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
<?php declare(strict_types=1);
22

3-
43
namespace SwoftTest\Proxy\Unit;
54

6-
75
use PHPUnit\Framework\TestCase;
86

97
/**
@@ -17,4 +15,4 @@ public function testA()
1715
{
1816
$this->assertTrue(true);
1917
}
20-
}
18+
}

src/rpc-client/src/Annotation/Parser/ReferenceParser.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
<?php declare(strict_types=1);
22

3-
43
namespace Swoft\Rpc\Client\Annotation\Parser;
54

6-
75
use PhpDocReader\AnnotationException;
86
use PhpDocReader\PhpDocReader;
97
use ReflectionException;

src/rpc-client/src/Concern/ServiceTrait.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
*/
2121
trait ServiceTrait
2222
{
23-
2423
/**
2524
* @param string $interfaceClass
2625
* @param string $methodName
@@ -30,6 +29,7 @@ trait ServiceTrait
3029
* @throws ConnectionPoolException
3130
* @throws RpcClientException
3231
* @throws RpcResponseException
32+
* @noinspection MagicMethodsValidityInspection
3333
*/
3434
protected function __proxyCall(string $interfaceClass, string $methodName, array $params)
3535
{

src/rpc-client/src/Proxy/Ast/ProxyVisitor.php

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
use PhpParser\NodeTraverser;
99
use Swoft\Proxy\Ast\Visitor\Visitor;
1010
use Swoft\Rpc\Client\Concern\ServiceTrait;
11+
use Swoft\Stdlib\Helper\Str;
1112
use function array_unshift;
1213
use function sprintf;
13-
use function uniqid;
1414

1515
/**
1616
* Class ProxyVisitor
@@ -20,28 +20,28 @@
2020
class ProxyVisitor extends Visitor
2121
{
2222
/**
23-
* Namespace
23+
* Namespace. eg: "App\Rpc\Lib"
2424
*
2525
* @var string
2626
*/
2727
private $namespace = '';
2828

2929
/**
30-
* New class name
30+
* New class name suffix. eg: "IGNORE_5e92a0ad04171"
3131
*
3232
* @var string
3333
*/
3434
private $proxyId;
3535

3636
/**
37-
* Origin class name
37+
* Origin interface class name. eg: "App\Rpc\Lib\UserInterface"
3838
*
3939
* @var string
4040
*/
4141
private $originalInterfaceName = '';
4242

4343
/**
44-
* Proxy class name without namespace
44+
* Proxy class name without namespace. eg: "UserInterface_IGNORE_5e92a0ad04171"
4545
*
4646
* @var string
4747
*/
@@ -57,13 +57,15 @@ class ProxyVisitor extends Visitor
5757
/**
5858
* ProxyVisitor constructor.
5959
*
60+
* TODO 提前传入原类名,可以直接得到 namespace, proxyName, originalInterfaceName
61+
*
6062
* @param string $proxyId
61-
* @param string $TraitClassName
63+
* @param string $traitClassName
6264
*/
63-
public function __construct(string $proxyId = '', string $TraitClassName = ServiceTrait::class)
65+
public function __construct(string $proxyId = '', string $traitClassName = ServiceTrait::class)
6466
{
65-
$this->serviceTrait = $TraitClassName;
66-
$this->proxyId = $proxyId ?: uniqid();
67+
$this->serviceTrait = $traitClassName;
68+
$this->proxyId = $proxyId ?: Str::getUniqid();
6769
}
6870

6971
/**
@@ -83,7 +85,8 @@ public function enterNode(Node $node)
8385

8486
// Origin interface node
8587
if ($node instanceof Node\Stmt\Interface_) {
86-
$name = $node->name->toString();
88+
$name = $node->name->toString();
89+
8790
$this->proxyName = sprintf('%s_%s', $name, $this->proxyId);
8891
$this->originalInterfaceName = sprintf('%s\\%s', $this->namespace, $name);
8992

@@ -141,10 +144,10 @@ public function afterTraverse(array $nodes)
141144
/** @var Node\Stmt\Class_ $classNode */
142145
$classNode = $nodeFinder->findFirstInstanceOf($nodes, Node\Stmt\Class_::class);
143146

144-
$traitNode = $this->getTraitNode();
145-
$originalMethodNode = $this->getOriginalClassNameMethodNode();
147+
$traitNode = $this->getTraitNode();
148+
$orgMethodNode = $this->getOriginalClassNameMethodNode();
146149

147-
array_unshift($classNode->stmts, $traitNode, $originalMethodNode);
150+
array_unshift($classNode->stmts, $traitNode, $orgMethodNode);
148151
return $nodes;
149152
}
150153

0 commit comments

Comments
 (0)