連載
» 2005年03月16日 12時00分 公開

「AspectWerkz」の利用法アスペクト指向のバリエーション解説(4)

[米山学(クロノス 専務取締役),@IT]

 今回紹介するAspectWerkzは、Codehausで開発されているアスペクト指向フレームワークである。CodehausはJavaのオープンソースソフトウェアの開発を行っているプロジェクトであり、軽量コンテナである「PicoContainer」を開発していることでも知られている。このAspectWerkzは米BEAシステムズがスポンサーとなって開発を支援しているが、ライセンスはLGPL形式で配布されているため、AspectJやJBossAOPと同様に無償での商用利用が可能である。

AspectWerkzとは?

 AspectWerkzの特徴はPOJOであること、XMLの定義ファイルを用いてポイントカットやアドバイスを定義すること、そしてアノテーション(JSR-175)をサポートしていることなどが挙げられ、JBoss AOPとの共通点も多い。またEclipseプラグインが提供されていることなども開発者にとっては喜ばしいことだろう。さらに、公開されているベンチマークテストによって示されるように、非常にパフォーマンスが高いことも長所として挙げることができる。

 ところで、AspectWerkzに関しては、この記事を執筆中に興味深いコメントが発表された。連載の第2回目「AspectJから学ぶアスペクト指向の理解」で紹介した、eclipse.orgによって開発されているAspectJと統合され、AspectJ5という名前で開発が続けられるようだ。現在、ちまたではさまざまなアスペクト指向フレームワークが乱立しており、開発者が混乱するもととなっている。しかしながら、今後は主流となるAOPフレームワークに統一されていくのではないだろうか。

AspectWerkzのインストールとサンプルプログラムの実行

 では早速AspectWerkzをインストールして、いつものように簡単なサンプルプログラム「Hello, AspectWerkz」を実行してみよう。まずはAspectWerkzのサイトからアーカイブをダウンロードする。

 原稿執筆時点での最新バージョンはAspectWerkz 2であり、RC3版(aspectwerkz-2.0.RC3)がリリースされている。まずはこのファイルをダウンロードし、任意のディレクトリに解凍・展開する。

 次に環境変数の設定を行う。AspectWerkzを使用するためには環境変数「ASPECTWERKZ_HOME」を設定しなければならない。この環境変数にはAspectWerkzのホームディレクトリを指定する。

 さらに、AspectWerkzの「bin」ディレクトリを環境変数PATHに追加し、「lib」ディレクトリ下にある2つのJARファイル「aspectwerkz-2.0.RC3.jar」と「aspectwerkz-core-2.0.RC3.jar」をクラスパスに設定しておく。


「ASPECTWERKZ_HOME\bin」ディレクトリにあるバッチファイル「setEnv」を実行することで、自動的に必要なクラスパスの設定が行われる。


 ここまでで準備は完了である。では実際にAspectWerkzを使ったアスペクトのウィービングを行ってみよう。

 まずは、前回、前々回に使用した「Messenger」クラスと「Tester」クラスを用意する。すでに連載記事中で説明しているようにシンプルなJavaのプログラムである。

public class Messenger {
    public static void printMessage(String name) {         System.out.println(name);
    }
}
リスト1 Messenger.java

public class Tester {
    public static void main(String[] args) {         Messenger.printMessage("AspectWerkz");
    }
}
リスト2 Tester.java

 次にアスペクトを定義する。AspectWerkzではJBossAOPと同様、POJOによってアスペクトを定義するため、以下のような通常のJavaクラスを作成すればよい。

import org.codehaus.aspectwerkz.joinpoint.JoinPoint;
public class GreetingAspect {
    public void beforeGreeting(JoinPoint joinPoint) {
        System.out.print ("Hello, ");
    }
}
リスト3 GreetingAspect.java

 いつもと同じように「Hello,」を表示するアドバイスの実装を行っている。ここでアドバイスとして呼び出されるメソッドはJoinPointオブジェクトを引数に受け取るようにしておけば、後々ジョインポイントの情報を取得することができる。

 ポイントカットやアドバイスはXMLファイルを用いて次のように定義する。このファイルは「META-INF」ディレクトリ下に「aop.xml」という名前で格納しておくことで、アプリケーション実行時に自動的に読み込まれる。

<aspectwerkz>
    <system id="AspectWerkzExample">
        <aspect class="GreetingAspect">
            <pointcut name="greetMethod"
                        expression="execution(* Messenger.printMessage(..))" />
            <advice name="beforeGreeting" type="before"
                    bind-to="greetMethod" />
        </aspect>
    </system>
</aspectwerkz>
リスト4 aop.xml

 このaop.xmlでの記述を簡単に説明しておこう。エレメントのclass属性には、アドバイスを実装しているクラスを指定する。そしてサブエレメントのエレメントでexpression属性を用いてジョインポイントを指定する。ここではMessengerクラスのprintMessage()メソッドの呼び出しをジョインポイントとするように定義しているが、この記述方法の詳細についてはAspectWerkzのドキュメントを見てもらいたい。最後にエレメントによってアドバイスのタイプと呼び出すメソッドを、そしてどのポイントカットにバインドするのかを指定している。このとき、type属性にbeforeを指定することで、メソッド呼び出しの前に処理を挟み込むことができる。

 3つのファイルが用意できたら、ソースをコンパイルしてアスペクトをウィービングし、プログラムを実行してみよう。AspectWerkzでは、まず通常のjavacでコンパイルを行い、その後アスペクトのウィービングを行う。

> javac *.java
通常のコンパイル

 この時点ではアスペクトのウィービングは行われていない。試しにTesterを実行してみよう。

> java Tester
AspectWerkz
通常のコンパイル

 printMessage()メソッドの実行結果が表示される。次にアスペクトのウィービングを行ってみよう。次のようにaspectwerkzコマンドを用い、-offlineオプションにaop.xmlファイルの場所を指定し、最後に対象となるファイルの配置されているディレクトリを指定する。

> aspectwerkz -offline META-INF/aop.xml .
( 4 s )SUCCESS: .
アスペクトのウィービング

 ウィービングが完了したら、もう1度アプリケーションを実行する。

> java Tester
Hello, AspectWerkz
Testerの実行

 アドバイスで実装した「Hello, 」を表示する処理が差し込まれていることが分かる。この例ではコンパイル時の静的なウィービングを紹介したが、AspectWerkzでは実行時の動的なウィービングもサポートしている。その場合にはアプリケーション実行時にjavaコマンドではなくaspectwerkzコマンドを用いる。

 いったん、アスペクトのウィービング済みクラスファイルを削除し、もう一度コンパイルから動的なウィービングによる実行を試してみよう。

> javac *.java
>aspectwerkz -cp . Tester
AspectWerkz - INFO - Pre-processor org.codehaus.aspectwerkz.transform.
AspectWerkzPreProcessor loaded and initialized
Hello, AspectWerkz
動的なウィービング

実行時情報の取得

 AspectWerkzで実行時のジョインポイントの情報を取得するにはorg.codehaus.aspectwerkz.joinpointパッケージに定義されているRtti(ReturnTime Type Information)インターフェイスを用いる。Rttiオブジェクトから得られる情報はロギングやトレースの際に必要となるだろう。

 Rttiを取得するには次のようにJoinPointオブジェクトのgetRtti()メソッドを使用する。

Rtti rtti = JoinPoint.getRtti();

 Rttiオブジェクトが取得できれば、例えば次のようにgetDeclaringType()メソッドやgetName()メソッドを呼び出すことでジョインポイントのクラス名やメソッド名を表示することができる。

    System.out.println("Class:" + rtti.getDeclaringType());
    System.out.println("Name:" + rtti.getName());


 今回はAspectWerkzを紹介したが、冒頭でも伝えたように今後はAspectJ5と統合されていく流れになっている。この1年ほどでAOPフレームワークも洗練されてきており、ある程度統一も図られていくだろう。これまではアスペクト指向とAOPの基礎的な概念およびAOPフレームワークの導入について簡単に紹介してきたが、次回はもう少し実践的なAOPの活用例を紹介したい。




Copyright © ITmedia, Inc. All Rights Reserved.

注目のテーマ