PR

DIコンテナを利用した実装方法

 DIコンテナのメリットがつかめたところで,DIコンテナを利用する際の実装方法を見ていきましょう。まず,お嬢様薫子がリムジンでドライブする例の実装方法を説明し,次に,使用する車がスポーツカーに変更したときの対応方法について確認します。

 このサンプルは,どんな車でドライブするのかをコンソールに出力する単純なもので,登場するクラスは以下の通りです。

  • Mainクラス・・・サンプルアプリケーションの起動クラス
  • Personクラス(お嬢様)・・・Carを使用する人
  • Carインタフェース(車)・・・ドライブができる車
  • Limousineクラス(リムジン)・・・Carの実装クラス
  • SportsCarクラス(スポーツカー)・・・Carの実装クラス

 クラス構成は,図6になります。LimousineクラスとSportsCarクラスだけでなく,PersonクラスもDIの管理領域に含まれる点に注意しましょう。

図6●サンプルのクラス構成
図6●サンプルのクラス構成
[画像のクリックで拡大表示]

 サンプルのプロジェクト構成は,図7の通りです。使用するSpringのバージョンは2.0.5です。統合開発環境には,Eclipse 3.2とJava SE 5.0を用います。必要なjarファイルは,すべてSpringに同梱されています。

図7●プロジェクト構成
図7●プロジェクト構成

 では,実装方法を確認していきましょう。

1. CarインタフェースとLimousineクラスの作成

 Carインタフェース(リスト1)と,その実装クラスであるLimousineクラス(リスト2)を,以下の通りに作成します。


package sample;
public interface Car {

  public String drive();

}
リスト1●Carインタフェース


package sample;
public class Limousin implements Car {

  public String drive() {
    String msg = "リムジンでドライブ!!";
    return msg;
  }
}
リスト2●Limousineクラス

2. Personクラスの作成

 Carインタフェースを使用するPersonクラス(リスト3)を作成します。

リスト3●Personクラス
リスト3●Personクラス

(1)Carインタフェースを宣言します。
(2)LimousineオブジェクトをCarインタフェースに設定するためのセッター・メソッドを用意します。DIコンテナは,このセッター・メソッドを用いて,生成したLimousineオブジェクトをこのPersonクラスにセットします。
(3)getPlanメソッドを実装します。このメソッドは,Carインタフェースのdriveメソッドを実行して取得できた文字列を返します。

 Personクラスでは,Carインタフェースのdriveメソッドを実行していますが,その実装クラスのLimousineクラスは,どこにも出てこない点に注目してください。

3. Bean定義ファイルの作成

 これまで作成してきたクラスをBean定義ファイルに定義します。このBean定義ファイルを元にDIコンテナがオブジェクトを生成し,オブジェクト同士の関連付け作業をすることになります。ここでは,Bean定義ファイルをapplicationContext.xmlという名前でsampleパッケージの下に保存します(リスト4)。

リスト4●applicationContext.xml
リスト4●applicationContext.xml

(1)LimousineクラスをcarImplというIDで定義します。
(2)PersonクラスをpersonというIDで定義します。
(3)Personクラスの“car”プロパティに,(1)で定義した“carImpl”をセットすることを意味します。propertyタグのname属性は,Personクラスで宣言したプロパティ名と同じでなければなりません。この設定で,Personオブジェクトのcarプロパティに(1)で定義したLimousineオブジェクトが設定されます。

4. Mainクラスの作成

 サンプル・アプリケーションを起動するMainクラスを作成します(リスト5)。

リスト5●Mainクラス
リスト5●Mainクラス

(1)Bean定義ファイルを元にDIコンテナを作ります。この時点で,PersonオブジェクトのcarプロパティにLimousineオブジェクトをセットします。
(2)手順1で取得したBean定義ファイルから,“person”というIDで定義されたBeanを取得します。
(3)person.getPlan()を実行して,取得した文字列をコンソールに出力します。

 このMainクラスを実行すると,コンソールに以下のように出力されます。

明日の予定はリムジンでドライブ!!

 Personクラスのプログラム上はCarインタフェースを呼び出していますが,実行時にはLimousineクラスが呼び出されています。

 次に,LimousineクラスからSportsCarクラスに変更になったケースを見ていきましょう。と言っても,手順は簡単です。Limousineクラスと同様にSportsCarクラスを作成し,Bean定義ファイルの変更を行うだけです。

5. SportsCarクラスの作成

 Carインタフェースを実装するSportsCarクラスを以下のように作成します(リスト6)。


package sample;
public class SportsCar implements Car {

  public String drive() {
    String msg = "スポーツカーでドライブ!!";
    return msg;
  }
}
リスト6●SportsCarクラス

6. Bean定義ファイルの修正

 手順3で作成したBean定義ファイル(applicationContext.xml)を以下のように変更します(リスト7)。


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">

  <bean id="person" class="sample.Person">
    <property name="car" ref="carImpl"/>
  </bean>
  
  <!--<bean id="carImpl" class="sample.Limousin"></bean>-->
  <bean id="carImpl" class="sample.SportsCar"></bean>

</beans>
リスト7●applicationContext.xml

 これでPersonクラスには,Limousineオブジェクトではなく,SportsCarオブジェクトがセットされます。

 手順4の後に実行したメインクラスを再度実行すると,今度はコンソールに以下のように,SportsCarオブジェクトで設定した文字列が出力されます。

明日の予定はスポーツカーでドライブ!!

 このように,既存のクラスに変更を加えなくても,Bean定義ファイルを変更するだけで,Personクラスで使用するオブジェクトの変更ができました。SpringのDIコンテナを用いれば,機能の変更が簡単にできることを確認していただけたと思います。

おわりに

 DIコンテナを用いることで,クラス間の関係をソースコードに明記する必要がないことがおわかりいただけたと思います。これが,冒頭で言った“オブジェクト間の疎結合を可能にする”の意味です。DIコンテナを使用すると,Bean定義ファイルを管理しなければならない手間が増えますが,「変更が容易である」「インタフェース・プログラミングをすることで保守性が高まる」などのメリットがあります。

 次回は,AOPについて説明します。