← 解説「DI コンテナを素の Java で作る」に戻る
サンプルコードで身につける: DI コンテナを素の Java で作る
解説で学んだ概念を、5つの具体例で確認します。素朴な例から実務寄りの例へと進みます。
1コンストラクタの引数の型を読むだけ
を作る前に、材料になる1手だけを取り出します。からを取り出し、getParameterTypes で引数の型を並べます。どのクラスが何を必要とするかは、ソースに書いた引数がそのまま答えになっています。
Java
2対比: コンテナなしで、手で順番に new する
同じ3クラスをコンテナなしで組み立てた形です。作る順番(Clock が先)と、同じ Clock を2か所に渡すことを、人が に書いています。クラスが増えるたびに足すことになるこの組み立ての行が、コンテナの肩代わりする部分です。
Java
3依存を1つ足しても、コンテナと main は変わらない
UserService の引数に AuditLog を足した版です。コンテナにも main にも AuditLog という名前は出てきませんが、引数の型から見つけて作られます。Clock は3か所から要求されていますが、new Clock の出力は1回だけです。
Java
4うまくいかない場合: 循環する依存
A が B を、B が A を要求すると、置き場に入る前に同じ get が呼ばれ続け、スタックが尽きて になります。下の実物は捕まえずに終了させたとき( 25)の冒頭で、全 1025 行のうち 1019 行が MiniContainer.get でした(上の数行は回によって変わります)。これは自作版の挙動で、 も同じになるとは言えません。
Exception in thread "main" java.lang.StackOverflowErrorat java.base/java.lang.reflect.Constructor.copy(Constructor.java:148)at java.base/java.lang.reflect.ReflectAccess.copyConstructor(ReflectAccess.java:64)at java.base/jdk.internal.reflect.ReflectionFactory.copyConstructor(ReflectionFactory.java:173)at java.base/java.lang.Class.copyConstructors(Class.java:3238)at java.base/java.lang.Class.getDeclaredConstructors(Class.java:2354)at MiniContainer.get(prog.java:21)at MiniContainer.get(prog.java:25)at MiniContainer.get(prog.java:25)at MiniContainer.get(prog.java:25)...
Java
5うまくいかない場合: 引数がインターフェース
引数の型がでも、型の名前は実行時に読めます(出力の1行目)。ただしインターフェースは new できず、どの実装クラスを作るかを決める手がかりが、この自作コンテナにはありません。Spring は、コンテナが管理している(次の回で と呼びます)の中から型の合うものを探すことで、この先を解決します。
Java