AspectJ5 アノテーションベース開発を試した
これはjavacコマンドのコンパイルだけで開発できちゃうAspectJのこと。
さらにjavaコマンドのjavaagentで実行時のクラスロード時にweaveしちゃうことも可能。
そこで実際に実行してみた。小さい例ですが、結果はうまくいきました。
実行環境はJDK1.5.0_4を使ってます(ちなみに古い1.5.0ではjavacで例外が出ます^^;)
にある、aspectj-DEVELOPMENT-20050620091600.jarをダウンロード。unzipで展開(インストールせずw、もちろんEclipseなんかも使わない)
libのjarのうち、aspectjrt.jarがランタイム(Annotationを含む)、aspectjweaver.jarがロードタイムウィーバーであり、これだけを使用する。
まず、なんかweave対象を用意。ビルドしておく。
public class Main { public static void main(String[] args) { new Main().doNothing(); } public void doNothing() { } }
$ javac Main.java $ jar cvf main.jar Main.class
つぎにAspectを用意。
import org.aspectj.lang.annotation.*; @Aspect public class TestAspect { @Pointcut("call(* Main.*(..))") public void anyCall() {} @Before("anyCall()") public void logging() { System.out.println("log"); } }
そしてコンパイル。
$ javac -classpath lib/aspectjrt.jar;. TestAspect.java $ jar cvf myaspect.jar TestAspect.class
コンパイルに少し時間かかるけどやけにあっさりしてますw
ふと思ったけど、これってAspectに対してもAspectかけられるのかな。これができると一気に強力なツールになるんじゃないのだろうか。。。やってみたら無理でした。単にAspectクラスは以前のAspectJと同じでコードテンプレートとして使っているだけ。せっかくこういう仕様なら、そうじゃなくインスタンス化して呼び出したほうがいいと思う。けど、気ままな拡張がAspectJでそういうことをできなくしてしまったのだろう。
以下、ロードタイムウィービングのやり方です。
まずMETA-INF/aop.xmlを用意。これはaspectをクラスロード時にweaveする仕様を書いておく。
(なぜかXML宣言が消えますね^^;)
設定ファイルは、AspectWerkzの流れを汲んでいるようで、いろいろできるっぽいけど、あまり複雑なことはしないほうがいいでしょう。weaverとaspectどちらで位置を指定するとよいかというのも、まだ方法論があるわけでもないですし。
クラスの所属ではなく、単にクラスローダーが作成された時点ですべてに対してgetResourceAsStreamでMETA-INF/aop.xmlを読み込みにいくようなので、これは単独でjarにしておくことでも取り込み可。
$ jar cvf weaver.jar META-INF/aop.xml
で、実行(実際は一行)
$ java -classpath lib/aspectjrt.jar;main.jar;myaspect.jar;weaver.jar -javaagent:lib/aspectjweaver.jar Main
結果
WeavingAdaptor.weaveClass Main weaveinfo Type 'Main' (Main.java:3) advised by before advice from 'TestAspect' (TestAspect.java) WeavingAdaptor.weaveClass TestAspect log
weaver.jarをはずすとweaveされない
$ java -classpath lib/aspectjrt.jar;main.jar;myaspect.jar -javaagent:lib/aspectjweaver.jar Main WeavingAdaptor.weaveClass Main
aspectjweaver.jarの使い方はjavaagentだけじゃなく、-Djava.system.class.loader=で指定したり、プログラム内でClassLoaderを作ることも可能になるらしい(けど、どのClassLoaderクラスでしょう?まだない?)。
このやり方はとてもよい。ビルドなどのレベルで、ajcとかいろいろコマンドやオプションを使い分けたり覚えなくてもいいからね。