第2回「AspectJから学ぶアスペクト指向の理解」の記事ではeclipse.orgの下で開発されているAspectJを取り上げ、実際にAOPを体験してもらった。今回は「JBoss AOP」を紹介しよう。その名前からも分かるとおり「JBoss AOP」はJBossプロジェクトにおいて開発されている「アスペクト指向フレームワーク」である。
JBossプロジェクトはオープンソースのJ2EEサーバである「JBoss AS」を開発、提供していることで有名だが、AOPフレームワークの開発にも力を入れている。このAOPフレームワークは「JBoss AOP」と呼ばれており、JBoss ASにもその仕組みが取り入れられている。特に、現在早期ドラフト版が公開されているEJB 3の仕様では、JDK 5から新しく導入されたアノテーションの仕組みを採用しており、アスペクト指向とアノテーションとのかかわりも興味深い。JBoss 4.0.1 RC2ではEJB 3のテスト実装が行われており、それらの機能を実際に動かしてみることができる。本稿でもその辺りを少しだけ紹介しているので、ぜひ試していただきたい。
では、早速JBoss AOPをダウンロードしてセットアップしてみよう。まずは、JBossのサイトから「JBoss AOP」のページを開き、「Downloads」のリンクより最新のアーカイブ(本稿執筆時「jboss-aop_1.0.0-FINAL.zip」)をダウンロードする。ダウンロードしたアーカイブを任意のディレクトリに解凍・展開すれば準備完了である。
では、前回と同じように簡単なサンプルプログラムを例に、JBoss AOPによるアスペクト指向プログラミングを試していこう。前回の記事で紹介した
public class Messenger { public static void printMessage(String name) { System.out.println(name); } }
public class Tester { public static void main(String[] args) { Messenger.printMessage("JBoss AOP"); } }
を見てほしい。ここまでは前回のサンプルコードと同じである。MessengerクラスにはString型の引数を1つ取るpirntMessage()というメソッドが定義されており、Testerクラスはそのメソッドに「JBoss AOP」という文字列を渡して呼び出す。ここに、「Hello,」を先頭に加える。
AspectJでは「アドバイス」や「ポイントカット」を定義するために、独自のキーワード「aspect」を用いた「アスペクト」を作成したが、JBoss AOPでは「インターセプタ」と呼ばれるPOJO(Plain Old Java Object)クラスを使用する。つまりAspectJのようにJavaの拡張仕様を用いるのではなく、通常のJavaのクラスを用いてアスペクトの振る舞いを記述することになる。
このインターセプタとなるクラスはorg.jboss.aop.advice.Interceptorインターフェイスを実装しなければならない。パッケージ名からも分かるとおり、アスペクト指向における「アドバイス」を記述するためのインターフェイスとなる。Interceptorには2つのメソッド「getName()」と「invoke()」が定義されており、implementsしたクラスで適切に実装しなければならない。ここでは以下のように、文字列「Hello, 」を挿入するインターセプタとなる「GreetingInterceptor」を作成する。
import org.jboss.aop.joinpoint.Invocation; import org.jboss.aop.advice.Interceptor; public class GreetingInterceptor implements Interceptor { public String getName() { return " GreetingInterceptor"; } public Object invoke (Invocation invocation) throws Throwable { try { System.out.print("Hello, "); return invocation.invokeNext(); } finally {} } }
getName()メソッドは単純に自身の名前を返すだけである。重要となるのはinvoke()メソッドであり、ここにアドバイスとなる実際の処理を記述する。またこのメソッドでは引数で受け取ったInvocationオブジェクトのinvokeNext()メソッドを呼び出して次のインターセプタを返すようにする。
ここで読者は「ポイントカット」の定義がないことに気付いたかもしれない。AspectJではポイントカットの定義もアスペクトの中に一緒に書いてしまっていたが、JBoss AOPではXMLファイルを用いてポイントカットを定義する。具体的には「jboss-aop.xml」という次のようなファイルを用意する。
<?xml version="1.0" encoding="UTF-8"?> <aop> <bind pointcut="execution(* Messenger->printMessage(..))"> <interceptor class="GreetingInterceptor" /> </bind> </aop>
ここでは
ここまでで必要なファイルの記述が終わったら、ソースコードをコンパイルしよう。JBoss AOPのコンパイルには通常のjavacに加えて、JBoss AOPフレームワークが提供する「AOPC」コンパイラが必要となる。また、いくつかのライブラリをクラスパスに設定する必要があるため今回は次のようなbuild.xmlを用意し、Antを使ってビルドとプログラムの実行を行うことにする。
<project default="run"> <target name="prepare"> <property name="jboss.aop.root" value="C:\jboss-aop_1.0.0-FINAL" /> <property name="jboss.aop.lib" value="${jboss.aop.root}/lib" /> <path id="classpath"> <fileset dir="${jboss.aop.lib}"> <include name="*.jar" /> </fileset> <pathelement path="." /> </path> <taskdef name="aopc" classname="org.jboss.aop.ant.AopC" classpathref="classpath" /> </target> <target name="compile" depends="prepare"> <javac srcdir="." includes="**"> <classpath refid="classpath" /> </javac> <aopc compilerclasspathref="classpath" classpathref="classpath"> <classpath path="."/> <src path="."/> <aoppath path="jboss-aop.xml" /> </aopc> </target> <target name="run" depends="compile"> <java fork="yes" className="Tester"> <sysproperty key="jboss.aop.path" value="jboss-aop.xml" /> <classpath refid="classpath" /> </java> </target> </project>
Antを実行すると、「Hello, 」が先頭に追加されたメッセージが表示される。
このようにJBoss AOPを用いることで、メソッド呼び出しとメソッドの実行との間に何らかの「振る舞い」を挿入することができる。ちなみにAspectJではこれをウィービングと呼んでいるが、JBoss AOPでは「メソッドインターセプション」と呼んでいる。AspectJとJBoss AOPとの一番大きな違いは、AspectJが独自のJava拡張構文を用いるのに対し、JBoss AOPではあくまでも普通のJavaクラス、いわゆるPOJOを使っている点にある。ぜひ、もう一度AspectJの実装と比べて両者の違いを確認していただきたい。
Copyright © ITmedia, Inc. All Rights Reserved.