BEAR.Sunday/Ray.Di/Ray.Aopコードリーディングメモ
BEAR.Skeleton ~0.10 で作成したアプリを ~1.0@dev に上げる作業をしながらコードいっぱい読んだのでメモを残しておきます。自分用なので走り書きです。
モジュールの install と override
モジュールにモジュールをインストールする方法は intall と override の 2 通りある。
ドキュメント によると install は先に束縛を定義したものが優先されるが、override なら上書きできるとのこと。
実装を見ると Container
のマージの方法が異なるだけのよう。
を持っていて、Container::merge() を使ってマージされる。
マージのロジックを見ると、確かに
- install なら先勝ち
- override なら後勝ち
になっている。(配列に対する +
での加算は、同じキーに対して左項が残るのが PHP の仕様)
DI (bind)
AbstractModule::bind() の処理内容を見ると、Bind クラスのコンストラクタ に対し、
- 自分自身(AbstractModule)が持っている
Container
- 束縛したいインタフェースのクラス名
の 2 つを渡している。
さらにその後 Bind::to() が呼ばれると、預かっていた Container
に対して add($this) (=インタフェースと実クラスのバインディングをコンテナに登録)を行う。
Container::add() の中身を見ると、Bind->getBound()
で依存定義のオブジェクトを取得し、それを 依存に対する束縛(DI)のリスト に登録している。
登録の処理は Dependency::register() で行われている。
配列のキーは インタフェースのクラス名と AnnotatedWith (@Named) で付けられた名前をハイフンで接続した文字列 になる。
つまり、インタフェースのクラス名と @Named の名前の組が全く同じなら、同じ束縛として扱われる。
AOP (bindInterceptor)
AbstractModule::bindInterceptor() の処理内容を見ると、
-
Container
への Pointcut の追加 - インターセプタのクラス名に対してインターセプタのクラスを束縛(インターセプタの実クラスをコンテナにインジェクトさせるため?)
の 2 つのことを行っている。
Container
への Pointcut
の追加は キー指定なしで配列に push しているだけ なので、別のコンテナとマージされるとき は完全な先勝ちになる。(配列に対する + での加算は、同じキーに対して左項が残るのが PHP の仕様なので、キー指定なしでも 0
とか 1
とかのキーに対して先勝ちになる)
したがって、Ray.Di ~2.0@dev では、~1.0 でやっていたように AOP のバインディングを AppModule 以外に書いておいて install するというこは出来ない。(override すればできるけど、PackageModule からインストールしたバインディング が消えてしまう)
束縛が実際にインジェクトされるのはいつか?
BEAR.Sunday で実際に Ray の束縛がインジェクトされる仕組みはどうなっているのか?
DI
- bootstrap で BEAR.Sunday アプリケーションが作られる
- App が作られるときに、一番外側のコンテキスト のモジュールを元に Injector が作られる
- Injector が作られるときに、InjectorInterface に自分自身を束縛している
- Injector::getInstance で実際に依存オブジェクトを取り出している人は BEAR\Resouce\AppAdapter ぐらいしか見つからず、実行時に誰がどうやって依存オブジェクトを渡しているのかよく分からず…
AOP
- bootstrap で BEAR.Sunday アプリケーションが作られる
- App が作られるときに、一番外側のコンテキスト のモジュールを元に Injector が作られる
- Injector が作られるときに、コンテナの weaveAspects() が実行される
- コンテナの weaveAspects で、コンテナが持つ各依存の weaveAspects() が実行される
- Dependency::weaveAspects() ここから先は力尽きてあんまり読めてない…けど、下位の weaveAspects に伝播していく感じかなと想像してる
残った疑問
- AOP の別モジュールからの install が v0 → v1 で出来なくなったのはなぜだろう?(
Container::merge
を+
じゃなくarray_merge
にするだけで解決したりしないのかな?(しないんだろうけど)) - DI や AOP で実際に束縛が行われるまでのロジックがまだよく分からない
Discussion