J2EE関連の最新トピックをわかりやすく解説

J2EE Watch [7]


DIとAOPがサーバ・コンポーネント技術を変える






EJBオブジェクトから「DI+AOP」へ

 こうしたEJBの数々の問題点を解決しようとしているのが、DIとAOPの技術です。DIとAOPを使えば、素のJavaクラス、すなわちPOJO(Plain Old Java Object)に対してさまざまな機能を織り込めます。そのため、前ページで述べたようなEJBオブジェクトに縛られたEJBコンポーネントは不要になります(図3)。

図3 サーバ・コンポーネント技術の進化(ORM:O/Rマッピング、TX:TXインターフェイス、MVC:MVCフレームワーク、RPC:Remote Procedure Call)。TXインターフェイスとは、アプリケーションプログラムがトランザクションを開始したり、終了したり、また、その状態について問い合わせたりするためのAPIを規定するもの

 例えばSeasarでは、コンポーネントのメソッド呼び出しを以下の3行で記述できます。

S2Container container = S2ContainerFactory.create(PATH);
Foo foo = (Foo) container.getComponent(Foo.class);
foo.hello();

 まず1行目を見れば分かるように、Seasarでは開発者が書いたコードのスレッドでコンテナを用意するので、アプリケーション・サーバを起動しておく必要がありません。そのため、開発環境の構築やユニットテストの記述がとても簡単になります。コンテナの構成も一枚岩ではなく、必要な機能だけを選んでコンポーネントに付加できる構成になっています。

 続いて3行目では、POJOであるオブジェクトfooのメソッドhelloを呼び出しています。このときSeasarのコンテナは、メソッド呼び出しをインターセプトし、トランザクション制御をはじめとするさまざまな機能を付加します。Seasarでは、このインターセプトを実装する手段として、バイトコード変換ライブラリJavassistによるAOP(Aspect Oriented Programming)を利用しています。バイトコードを動的に修正することで、POJOのメソッドにフックを挿入し、EJBオブジェクトのような代理オブジェクトを使わずに各種コンテナ機能の織り込みを実現しています。

 また例えば、コンポーネント内部でデータベース・アクセスを行う場合、従来のEJBコンポーネントでは、DataSourceをJNDI経由で明示的に取得する必要がありました。これに対しSeasarでは、次のように記述してDataSourceを取得できます。

private DataSource dataSource_;

public EmployeeDaoImpl(DataSource dataSource) {
    dataSource_ = dataSource;
}

 この例では、「コンストラクタ・インジェクション」と呼ばれるDIにより、コンポーネント内で使用するDataSourceがコンテナによって後から注入されます。つまり、コンポーネントが必要とするさまざまなリソース(DBやメールサーバとのコネクションや、ほかのコンポーネントへの参照など)を「コンポーネントがコンテナから取得する」のではなく、「コンテナがコンポーネントに注入する」という形態です。そのため、コンテナのAPIに依存するコードをコンポーネント内部に記述する必要がありません。

XMLかアノテーションか

 もっとも、SeasarやSpringにおいても、DIやAOPの適用対象をコンテナに指示するための設定用XMLファイルが欠かせません。例えばコンストラクタ・インジェクションを用いるには、以下のような.diconファイルが必要となります。

<components>
    <component name="hello" class="examples.Foo">
        <arg>"Hello World!"</arg>
    </component>
</components>

 このように、外部XMLファイルでDIやAOPを設定するという構成には一長一短があります。「コードの外部依存性を減らせる」「コードがすっきりする」というメリットの一方で、「XMLファイルのメンテナンスが面倒」というデメリット(XML Hellとも呼ばれる)が生じます。そこでEJB 3.0仕様では、Java 5.0以降に導入された「アノテーション」により、DIやAOPの適用をコンテナに指示する手法が採用されています。

@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public int add(int x, int y) {
        return x + y;
    }
}

 この例では、「メソッドaddをインターセプトしてトランザクション制御を実施してほしい」という内容をEJBコンテナに指示しています。

 一方Seasarでも、データベース・アクセス機能を提供するコンテナS2Daoにおいて、ORMにおけるテーブルカラムとJavaフィールドの対応付けを実現する独自のアノテーションを採用しています(以下参照)。

public static final String employeeNo_COLUMN = "EMPNO";

 これらはいずれも、外部のXMLを用意する必要をなくし、XML Hellの負担から開発者を解放しようという試みです。

コンポーネントはDI+AOPで進化する

 コンポーネント・モデルの利点として「コンポーネントの再利用性」がしばしば挙げられます。しかしビジネス・ロジックは「個々のプロジェクト要件に固有なロジック」であるため、そもそも再利用や流通には向かないという印象を筆者は受けます。むしろ、普遍的なロジックをできるだけコンテナ側に追い出し、コンポーネントに織り込むことでそれを再利用するのが、コンポーネント・モデルの真価と考えます。

 DIとAOPをベースとしたコンテナが革新的な点は、POJOをそのままコンポーネントとして利用できることです。ですからDIコンテナは、軽量コンテナというより、むしろ「コンポーネントを軽量にするコンテナ」と表現した方が分かりやすいでしょう。従来のEJBコンポーネントのようにさまざまなルールやAPIに縛られた重量級のコンポーネントを捨て、開発やテストの容易なPOJOをそのまま軽量コンポーネントとして利用する。このDI+AOPのアプローチは、Webアプリケーション開発で必要とされる多種多様な機能をPOJOに織り込む手段として、優れた威力を発揮するはずです。


■関連記事

1/2  

 INDEX

J2EE Watch [7]
  Page1
DIコンテナ=軽量コンテナ?
なぜコンテナが必要か
コンポーネント・モデルEJBの長所と短所
EJBの「重さ」の理由
「一枚岩」なEJB仕様
  Page2
EJBオブジェクトから「DI+AOP」へ
XMLかアノテーションか
コンポーネントはDI+AOPで進化する

 




Java Solution全記事一覧

 



Java Agile フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Java Agile 記事ランキング

本日 月間