DIContainerのわかりやすい説明(ただし間違いを多く含む)

 結局よくわからなかったので、知り合いのSE劉紫氏にDIコンテナについて教えてもらいました。以下みはえるなりの理解(間違っていたらみはえるの理解ミスです)。なお、みはえるはC++プログラマでして、Javaの用語を全然知りません。この辺ご理解下さい。間違いがあったら気軽にコメントに書いて頂けると大変助かります。

 状況を3階層アプリケーションに限定するとします。3階層アプリケーションでは、ユーザの要求に対し、プレゼンテーション層→ビジネスロジック層→データ層と要求が伝播され、結果が返されます。結果が返るとセッションが一度切れるので、個々の層(特にビジネスロジック層)は状態を保持しない、つまりステートレスなコーディングスタイルになります。

 さて、ビジネスロジックの1つの機能を1つのクラスで表すとします。プレゼンテーション層からは、必要なクラスを1個呼び出すと、そのクラスが必要な処理を行ってくれるように見えます。このクラスは、大抵の場合、内部に多くのクラスを集約した、複合クラス(こんな用語はねーけど)になります。

 この複合クラスが持つ子クラスを、如何に初期化&設定するかがDIコンテナが持つテーマです。子クラスは、テスト時にはMockを与えたいかもしれないし、方針が途中で変わって実装が入れ替わるかもしれない。ですから子クラスの実装を決定するタイミングは、出来るだけ遅らせたいのです。

 これらは、インターフェイスと実装の分離により実現させます。問題は、どうやってインターフェイスと実装を繋ぎ合わせるかにあります。Dependency Injection(DI/依存性注入)のいくつかあるパターンのうち、Setter Injectionのでは、Setterメソッドによってクラス内のインターフェイスへのポインタ(Javaではポインタとは言いませんが)に子クラスを設定します。

 で、ここからがDIコンテナの本領発揮なのですが、DIコンテナに親クラスを登録しておくと、プレゼンテーション層がクラスを必要とした場合に、子クラスの検索と登録をDIコンテナが自動的に行ってくれるのです。これにより、子クラスの初期化と設定という頻出コーディングを省略する事が出来るのです。

 Seasar2での挙動を例にします。親クラスは、必要なSetterメソッドを実装して、DIコンテナに登録します。子クラスは、interfaceから継承して実装クラスを作り、そのクラスをXMLファイルに記述します。アプリケーション層は、自分が必要とするクラスをDIコンテナに要求します。するとDIコンテナは以下のような処理を行います。

  1. 要求されたクラスをコンテナ内から取得
  2. 取得したクラスのsetterメソッドを解析し、必要なinterfaceを発見
  3. interfaceからXMLファイルを辿って、子クラスの実装を発見
  4. 子クラスを初期化し、親クラスにInjection
  5. プレゼンテーション層に要求されたクラスを返す

 凄く簡単に言うと、これによって子クラスの初期化と設定作業が自動化されます。他にもPloxyクラスをはさんでAOPを実現するとか、機能は山ほどあるんですがよくわかってません(塩)

 とりあえず、DIコンテナをアダプタパターンと勘違いしていたみはえるはここらへんで修行の旅に出る事にしまつ(泣)