« 抽象化がもたらすリアル | メイン | 不安定であることの機敏性 »

DIコンテナとGenericsを利用して品質や効率をあげるテクニック

 今日、メンバーと話をしていて面白かったのでコーディングしてみました。


メタプログラミングっぽくDIコンテナを利用する
 XMLの名前空間をトリガーにしてローカル名でオブジェクトを発見し、処理を委譲するというアイデアです。例えば名前空間がcommandとして、そのローカル名でDIコンテナをルックアップします。

<コマンド定義ファイル test.xml>
<?xml version="1.0" encoding="UTF-8"?>
<commands xmlns:command="http://www.arclamp.jp/command">
  <command:out command:message="ほげほげ" />
</commands>


 DIコンテナの設定ファイルはこんな感じ。command:outという指定なので、commandsプロパティにoutというキーでBeanをインジェクトします。

<Springのサンプル設定ファイル test-applicationContext.xml>
<?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="parser" class="jp.arclamp.metadi.impl.ParserImpl">
    <property name="commands" >
      <map>
        <entry key="out">
          <bean class="jp.arclamp.metadi.commands.OutCommand"/>
        </entry>
      </map>
    </property>
  </bean>
</beans>


 コマンドを追加したいなら設定ファイルに新しいエントリを追加するだけで済みます(本当は名前空間に対応したxsdも必要でしょうが)。今回はXMLの名前空間をトリガーにして対象に処理をしていますが、もっとシンプルに要素名で処理をしてもいいでしょう。ここらへんはアイデアしだいということで。

 こういうことをしていると設定ファイルがDSLという位置づけになり、JavaコードはDSLのコンテナという理解をすることができます。


Genericsを利用したインターフェース定義
 もう1つはGenericsの活用。コマンドのクラス(この場合は(OutCommand)は、インターフェースCommandを実装しなくてはいけません。

<コマンドのインターフェース:Command.java>
package jp.arclamp.metadi;
public interface Command<T> {
  public void execute(T params);
}


 コマンドの実行メソッドexecuteのパラメタがGenericsで指定されています。なので、実装する場合は、次のような感じになります。パラメタオブジェクトを自分で指定できるのでコードが曖昧になりません。

<コマンドの実装クラス:OutCommand.java>
package jp.arclamp.metadi.commands;
import jp.arclamp.metadi.Command;
public class OutCommand implements Command<OutParameter> {
  public void execute(OutParameter parameter) {
    System.out.println(parameter.getMessage());
  }
}


<パラメタオブジェクトのクラス:OutParameter.java>
package jp.arclamp.metadi.commands;
public class OutParameter {
  private String message;
  public String getMessage() {
    return message;
  }
  public void setMessage(String message) {
    this.message = message;
  }
}


 コマンドオブジェクトを呼び出すときにはリフレクションAPIを使ってGenericsのクラスを取得しパラメタオブジェクトをインスタンス化します。あとはパラメタオブジェクトに対してXMLの属性に従ったセッターインジェクションで値を設定しています(リフレクションAPIによるDI処理)。


 こんな風にDIコンテナやGenericsを使うことでアプリケーションの部分を取り出してフレームワーク化すると、pojoを保ちつつ静的型付けを活かすことができます。品質や効率化についても貢献することでしょう。

 サンプルコード(Maven2対応)はこちら。自由に使ってください。適当コーディングなのでご注意を。あと、もっと良いアイデアがあったら教えてくださいね。

トラックバック

このエントリーのトラックバックURL:
http://www.arclamp.jp/mt33/mt-tracback.cgi/1962

コメントを投稿

(いままで、ここでコメントしたことがないときは、コメントを表示する前にこのブログのオーナーの承認が必要になることがあります。承認されるまではコメントは表示されません。そのときはしばらく待ってください。)

About

2007年05月08日 23:02に投稿されたエントリーのページです。

ひとつ前の投稿は「抽象化がもたらすリアル」です。

次の投稿は「不安定であることの機敏性」です。

他にも多くのエントリーがあります。メインページアーカイブページも見てください。

Creative Commons License
このブログは、次のライセンスで保護されています。 クリエイティブ・コモンズ・ライセンス.
Powered by
Movable Type