ひとつ前のエントリー:
僕はだいぶ以前から、いくつか(複数)の理由からAOPには興味があったのだけど、たまに横目で眺めている傍観者って感じで、自分で調べる気力が湧かなかったんだけど、ちょっと刺激されました。
んで、とりあえず、最近のAspectJコンパイラを使えるようにしましたよ。
ダウンロードとセットアップ
AspectJのWebサイトのダウンロードページから、最新安定版(Latest Stable Release)である「AspectJ 1.5.0, Released 20th December, 2005」をダウンロード。
ファイルはaspectj-1.5.0.jarですが、これ自体がJavaで書かれたインストーラなので、
としてインストールできます。すっげーお手軽で、これで好感を持ちました。
java -jar aspectj-1.5.0.jar
環境変数PATHとCLASSPATHを設定しておいたほうがいいです。例えば、AspectJのインストール先がC:\Java\aspectj1.5\だとして、
コンパイラコマンドはajc
(シェルスクリプトまたはバッチファイル)ですね。これを一回実行すれば、環境変数ASPECTJ_HOMEを(JAVA_HOMEも)設定してくれます。
%ASPECTJ_HOME%\doc\index.htmlからたどれるドキュメントはかなり充実している模様。%ASPECTJ_HOME%\doc\example\の下にサンプルもあります。
コンパイラの使い方
%ASPECTJ_HOME%\doc\examples\ltwに簡単な定番サンプルがあります(ltwはload-time weavingのサンプルですが、気にしないで借用)。
/* HelloWorld.java */
public class HelloWorld {
public static void main (String[] args) {
System.out.println("Hello World!");
}
}
/* Tracing.java */
public aspect Tracing {
private pointcut mainMethod () :
execution(public static void main(String[]));before () : mainMethod() {
System.out.println("> " + thisJoinPoint);
}after () : mainMethod() {
System.out.println("< " + thisJoinPoint);
}
}
まず、ajcはjavacの代わりに使えます。
C:\tmp>set CLASSPATH=%CLASSPATH%;.C:\tmp>ajc HelloWorld.java
C:\tmp>java HelloWorld
Hello World!C:\tmp>
javacではコンパイルできないAspectJ固有のコードもコンパイルできます。
C:\tmp>javac Tracing.java
Tracing.java:2: 'class' または 'interface' がありません。
public aspect Tracing {
^
エラー 1 個C:\tmp>ajc Tracing.java
C:\tmp>
しかし、クラスとアスペクトを個別にコンパイルしても、新しいことは何も起きません。アスペクト(この場合はTracing)をクラス(この場合はHelloWorld)に織り込むには次のようにします。
C:tmp>ajc HelloWorld.java Tracing.javaC:\tmp>java HelloWorld
> execution(void HelloWorld.main(String[]))
Hello World!
< execution(void HelloWorld.main(String[]))C:\tmp>
ajcに指定するソースファイルの順序は問いません。ajc *.java
でもOKです。ワイルドカードは次のようにも使えますね。
C:\tmp>mkdir srcC:\tmp>copy HelloWorld.java src
1 個のファイルをコピーしました。C:\tmp>mkdir aspects
C:\tmp>copy Tracing.java aspects
1 個のファイルをコピーしました。C:\tmp>ajc src/*.java aspects/*.java
C:\tmp>java -classpath %CLASSPATH%;src;aspects HelloWorld
> execution(void HelloWorld.main(String[]))
Hello World!
< execution(void HelloWorld.main(String[]))C:\tmp>
でも、上の方法ではクラスファイルが別々の場所に作られるので、次のほうがいいでしょう。
C:\tmp>mkdir classesC:\tmp>ajc -d classes src/*.java aspects/*.java
C:\tmp>java -classpath %CLASSPATH%;classes HelloWorld
> execution(void HelloWorld.main(String[]))
Hello World!
< execution(void HelloWorld.main(String[]))C:\tmp>
ワイルドカードを使わずとも、ソースディレクトリを指定することもできます。
C:\tmp>ajc -d classes -sourceroots src;aspectsC:\tmp>set CLASSPATH=%CLASSPATH%;.\classes
C:\tmp>java HelloWorld
> execution(void HelloWorld.main(String[]))
Hello World!
< execution(void HelloWorld.main(String[]))C:\tmp>
既に作成されているjarファイルに、アスペクトを後から織り込むこともできます。
C:\tmp>javac -d . src\HelloWorld.javaC:\tmp>jar cvf HelloWorld.jar HelloWorld.class
マニフェストが追加されました。
HelloWorld.class を追加中です。(入 = 426) (出 = 288)(32% 収縮されました)C:\tmp>ajc -d classes -injars HelloWorld.jar aspects/*.java
C:\tmp>java HelloWorld
> execution(void HelloWorld.main(String[]))
Hello World!
< execution(void HelloWorld.main(String[]))C:\tmp>
上のコマンドでは、HelloWorld.jarに含まれる各クラスに、コンパイルされたアスペクトが織り込まれ、結果として織り込み済みクラスファイルが生成されます。jarファイル自体は変更されません。出力も再びjarファイルにしたいなら、-outjar
オプション(outjarsではないから注意)が使えます。