HyperfにおけるInjectアノテーションの内部仕組み解説

HyperfのInjectアノテーションがnew演算子によるインスタンス生成時にでも動作する仕組みについて、開発者が以下の仕組みを解説しています。

プロキシクラス生成の条件

Hyperfはすべてのクラスに対してプロキシクラスを生成しません。/runtime/container/proxyディレクトリに保存されるプロキシファイルは、AOP(Aspect Oriented Programming)が必要なクラスに限定されます。

class InjectionAspect extends AbstractAspect { public array $targetAnnotations = [ Injection::class, ]; public function intercept(InvocationInterface $invocation) { return $invocation->proceed(); } }

Injectionアノテーションを含むクラスに対してのみプロキシ生成がトリガーされ、このアスペクトは実際のメソッド挙動の変更は行いません。

Composer自動ロードの利用

HyperfはComposerのautoloadメカニズムを利用してプロキシクラスのロードを強制します。

$loader = Composer::getLoader(); $proxyMap = (new ProxyScanner())->scan($loader->getClassMap(), BASE_PATH . '/runtime/proxy'); $loader->addClassMap($proxyMap);

classMap配列にオリジナルクラス→プロキシクラスのマッピングを登録することで、new演算子によるインスタンス生成時に自動的にプロキシが選択されます。

依存解決プロセス

プロキシコンストラクタ内でPropertyHandlerTraitを通じて依存解決が実行されます。

foreach ($properties as $property) { $annotation = PropertyAnnotationReader::read($property); if ($annotation instanceof Injection) { $container = ApplicationContext::getContainer(); $reflection = ReflectionManager::reflectProperty($property); $reflection->setValue($instance, $container->get($annotation->target)); } }

ReflectionManager経由でプロパティにアクセスし、DIコンテナからインスタンスを取得してバインディングを行います。

実装構造比較

要素オリジナルクラスプロキシクラス
トレイト使用なしProxyTrait, PropertyHandlerTrait
コンストラクタ通常の初期化__handlePropertyHandler呼び出し
メソッド実装通常実装クロージャにラップ

タグ: Hyperf AOP DI PHP Composer

5月18日 12:00 投稿