技術評論社「オープンソースJavaプロダクツ/JBoss記事」補足情報

最終更新日: 2004年3月30日

概要

技術評論社「オープンソースJavaプロダクツ」 JBoss記事(223~245ページ)の補足情報を提供します。

本稿執筆時(2004年2月)におけるJBoss 4の最新バージョンはJBoss 4.0.0DR2でしたが、その後、2004年3月25日にJBoss 4.0.0DR3がリリースされました。DR2からDR3の間に、JBoss AOPの仕様・実装に対して多くの修正が施された結果、DR2を対象に作成した3章サンプルプログラムがそのままではDR3上では動作しなくなってしまいました。

このページでは、最新版のJBoss AOPでサンプルプログラムを動作させたいという読者の方のために、DR3向けに修正した3章サンプルプログラムを提供し、DR2からDR3への変更情報を簡単にまとめます。

3章サンプルプログラムのDR3対応版

ダウンロード

aop-sample-DR3-20040330.zip

サンプルのインストール方法

アーカイブファイル中のREADME.txtをご覧ください。

JBoss AOP DR2からの主な変更点

JBoss 4.0.0DR3のAOP部分はJBoss AOP 1.0Betaとしてリリースされています。JBoss AOP 1.0BetaのドキュメントはJBoss Wiki上にありますので、JBoss AOP仕様の詳細はこのWikiページを参照してください。 DR2からDR3ではパフォーマンス向上をはじめとして様々な改善が見られますが、ここではDR2用の3章サンプルプログラムをDR3で動作させるための修正箇所をリストしておきます。

織り込みの方法

DR2ではAOPモジュールをデプロイするために専用のクラスロードが必要だったため、JBoss 4以外のアプリケーションサーバ上でJBoss AOPを動作させることは困難でした。DR3では、新たにPrecompilerがサポートされ、デプロイ以前の段階でクラスファイルに対して織り込みが出来るようになりました。

DR3ではAOPモジュールをデプロイするのに、(1)JBossサーバに対してホットデプロイする方法と、(2)PrecompileしたAOPモジュールを実行する、2つの方法が提供されています。後者のPrecompilerの方式を選択すれば、専用のクラスローダは要求されないので、TomcatやJBoss 3などの既存のサーバ上でもJBoss AOPを実行させることが可能になります。

しかし、DR3用のサンプルプログラムでは、JBoss上のトランザクションマネージャやデータベースを使った例ですので、(1)のJBossサーバにホットデプロイする方法を選択しました。(2)のPrecompileをする方式の例は、JBoss AOP 1.0Betaのチュートリアルにサンプルプログラムがたくさん用意されていますので、そちらを参考にしてください。

aop関連のpackage名の変更

DR2ではAOP関連のクラスはorg.jboss.aopの直下にあったのですが、DR3ではadoviceやjoinpointといった分類を増やすことでパッケージ階層が整理されました。

DR2:

import org.jboss.aop.*;
=>

DR3:

import org.jboss.aop.advice.Interceptor;
import org.jboss.aop.joinpoint.Invocation;
import org.jboss.aop.joinpoint.MethodInvocation;

Interceptor#invoke()の戻り値型の変更

DR3でのinvokeメソッドの戻り値の型がObject型へ変更されました。

DR2:

public InvocationResponse invoke(Invocation invocation) throws Throwable
=>

DR3:

public Object invoke(Invocation invocation) throws Throwable

InvocationTypeの廃止

ポイントカットの宣言によって、そのインタセプタがメソッドのものであることが指定できるようになったので、InvocationTypeによるInvocationの型の判別が不要になりました。

DR2:

  public InvocationResponse invoke(Invocation invocation) throws Throwable {
    if (invocation.getType() == InvocationType.METHOD) {
      MethodInvocation mi = (MethodInvocation) invocation;
  ...
=>

DR3:

  public Object invoke(Invocation invocation) throws Throwable {
      MethodInvocation mi = (MethodInvocation) invocation;
 ...

jboss-aop.xmlの記述

DR3では、XDocletのサポートが無くなったのでjboss-aop.xmlを手で書く必要があります(メタデータについては「参考: metadataのjavaDoc上の指定」にて後述)。

pointcutの指定方法(bindタグ)

DR3では、ポイントカットの定義方法が改善されました。DR2でのinterceptor-pointcutのような、タグごとにポイントカットの種類を用意するのではなく、bindタグのpointcut属性としてより柔軟なポイントカットの指定が可能になりました。以下の例では、pointcut="execution(public * sample.pojo.CounterImpl->*())"と書くことで、「CounterImplクラス中の任意のpublicメソッドの実行中」にインタセプタが処理されるように指定しています。この例では登場しませんが、ポイントカット式をANDやORで組み合わせることも可能です

注意: ここで明示的にgetNextValue()のようにメソッド名を指定することもできますが、DR2用のサンプルコードの設定に合わせてこのようにしています。

DR2:

<interceptor-pointcut class="sample.pojo.CounterImpl"
                        >
    <interceptors>
      <interceptor class="sample.aop.ProfileInterceptor"
                   >
      </interceptor>
      <interceptor class="sample.aop.TransactionInterceptor"
                   >
      </interceptor>
      <interceptor class="sample.aop.LockInterceptor"
                   >
      </interceptor>
      <interceptor class="sample.aop.PersistenceInterceptor"
                   >
      </interceptor>
    </interceptors>
  </interceptor-pointcut>
=>

DR3:

    <bind pointcut="execution(public * sample.pojo.CounterImpl->*())">
      <interceptor class="sample.aop.ProfileInterceptor"/>
      <interceptor class="sample.aop.TransactionInterceptor"/>
      <interceptor class="sample.aop.LockInterceptor"/>
      <interceptor class="sample.aop.PersistenceInterceptor"/>
    </bind>

アノテーションの指定方法(annotationタグ)

DR2のメタデータという表現がアノテーションという表現に改められ、メソッドの指定方法もより簡単になりました。

DR2:

  <class-metadata group="sample" class="sample.pojo.CounterImpl">
    <default>
      <trans-attribute>Supports</trans-attribute>
    </default>

    <method name="getNextValue">
      <method-params>
      </method-params>
      <prof-attribute>true</prof-attribute>
    </method>
    <method name="getNextValue">
      <method-params>
      </method-params>
      <trans-attribute>Required</trans-attribute>
    </method>
  </class-metadata>
=>

DR3:

 <annotation tag="tran" class="sample.pojo.CounterImpl">
  <default>
   <trans-attribute>Supports</trans-attribute>
  </default>
 </annotation>
 <annotation tag="tran" class="sample.pojo.CounterImpl">
  <method expr="long getNextValue()">
   <trans-attribute>Required</trans-attribute>
  </method>
 </annotation>
 <annotation tag="profile" class="sample.pojo.CounterImpl">
  <method expr="long getNextValue()">
   <prof-attribute>true</prof-attribute>
  </method>
 </annotation>

参考: metadataのjavaDoc上の指定

JavaDoc上のメタデータの定義方法が一新されました。@@を使ったタグの指定は、JSR-175の仕様(現在Public Beta)に合わせたものです。これをアノテーションといいます。DR2までのメタデータは、インタセプタのような「AOPの構成情報」とコンストラクタ/メソッド/フィールドへの「付加情報」が渾然一体となっていました。DR3では、後者の付加情報だけをJSR-175のアノテーションの形式に合わせたのです。

  /**
   * @@tran trans-attribute=Required
   * @@profile prof-attribute=true
   */

DR3では、アノテーションの処理にQDoxというツールを採用しています(将来的にはJDK 1.5のアノテーション機能を使うようにします)。JavaDoc上のアノテーションの指定は、(Antから起動可能な)アノテーションコンパイラによってmetadata-aop.xmlという別ファイルに生成されます。プログラマはインタセプタの宣言(<bind>)とアノテーションコンパイラによって生成されたアノテーションの宣言(<annotation>)をひとつのjboss-aop.xmlとしてまとめて記述します。

注意: JBossサーバにデプロイするときは、メタデータをAOPモジュールのMETA-INF/jboss-aop.xmlにまとめる必要がありますが、Precompiler方式では、織り込み済みのクラスを実行するときにjboss-aop.xmlとmetadata-aop.xmlを別々のファイルのまま扱うことができます。詳しくはjbossaop-1.0beta/docs/examples/metadata/build.xmlを参考にしてください。


ホーム