javassistでHelloWorldをやってみる
Seasar2で使われているjavassistが気になったので、HelloWorld程度のサンプルを動かしてさくっと触ってみる。
javassistとは
javassistは「クラスのバイトコードを直接書き換える」ことができ、東京工業大学の千葉先生による純日本製の技術です。
このJavassistを利用することで、難しいバイトコードを意識することなくクラスのバイトコードを外部から操作できるようになります。
というわけで、カンタンなサンプルコードを書いてみるす。
準備
まずは、javassistのライブラリをDLします。
http://www.jboss.org/javassist/
最新版っぽい3.4GAをDLして解凍してできたフォルダ内のjavassist.jarにクラスパスを通す。
メッセージ表示クラス
package javassist; public class HelloJavassist { public void showMessage() { System.out.println("Hello Javassist!!"); } }
メインクラス
MainクラスでHelloJavassist#showMessageを実行する際に、メソッド実行時の前と後ろにAOP的な処理を入れてみます。
package javassist; public class Main { public static void main(String[] args) { try { ClassPool cp = ClassPool.getDefault(); CtClass cc = cp.get("javassist.HelloJavassist"); cc.stopPruning(true); CtMethod m = cc.getDeclaredMethod("showMessage"); m.insertBefore("System.out.println(\"before statement\");"); m.insertAfter("System.out.println(\"after statement\");"); cc.writeFile(); Class clazz = cc.toClass(); HelloJavassist helloJavassist = (HelloJavassist) clazz.newInstance(); helloJavassist.showMessage(); } catch (Exception e) { e.printStackTrace(); } } }
んで、Main.javaを実行すると
before statement Hello Javassist!! after statement
と表示される。おお〜!うまくAOP的なことができたね。
ここで注意しないといけないのはMain#mainに記述されている以下の箇所だ。
cc.stopPruning(true);
コイツを書くのを忘れていると、下のようなExceptionで怒られるので要注意!!
java.lang.RuntimeException: toBytecode(): javassist.HelloJavassist was pruned. at javassist.CtClassType.checkPruned(CtClassType.java:1284) at javassist.CtClassType.toBytecode(CtClassType.java:1245) at javassist.CtClass.toBytecode(CtClass.java:1181) : :