cglib実習01
いまさらながら簡単なサンプルを作ってみる。
まずはinterceptされちゃうクラス。 aaa()の中からbbb()を呼んでみて、クラス内部からの呼び出しでInterceptorが効くのかどうかを見てみる。
package yamo;public class Foo {
public void aaa() {
Util.log("<aaa> start");
bbb();
Util.log("<aaa> end");
}public void bbb() {
Util.log("<bbb> start");
Util.log("<bbb> end");
}
}
次にinterceptorクラス。 対象メソッドの前後でinterceptor用のログを出力する。 MethodProxyの「invokeSuper」っていうネーミングあたりでinterceptorの仕組みを窺い知ることができる。
package yamo;import java.lang.reflect.*;
import net.sf.cglib.proxy.*;public class LogInterceptor implements MethodInterceptor {
public Object intercept(Object obj, Method method,
Object[] args, MethodProxy proxy) throws Throwable {Object ret = null;
try {
Util.log(obj.getClass(), method, "start Intercepter");
if(!Modifier.isAbstract(method.getModifiers())) {
ret = proxy.invokeSuper(obj, args);
}
} finally {
Util.log(obj.getClass(), method, "end Intercepter");
}return ret;
}
}
そしてログ用のユーティリティクラス。
package yamo;import java.lang.reflect.*;
public final class Util {
public static void log(Class clazz, Method method, String msg) {
log("[" + clazz.getName() +"][" + method.getName() + "]" + msg);
}public static void log(String msg) {
System.out.println(msg);
}
}
いよいよメイン処理のクラス。
package yamo;import net.sf.cglib.proxy.*;
public class Main {
public static void main(String[] args) {
Foo foo = (Foo)newInstance(Foo.class);
Util.log("========================================");
Util.log("<<" + foo.getClass().getName() + ">>");
Util.log("========================================");
foo.aaa();foo = new Foo();
Util.log("========================================");
Util.log("<<" + foo.getClass().getName() + ">>");
Util.log("========================================");
foo.aaa();
}public static Object newInstance(Class clazz) {
try {
LogInterceptor interceptor = new LogInterceptor();
Enhancer en = new Enhancer();
en.setSuperclass(clazz);
en.setCallback(interceptor);
Object target = en.create();
return target;
} catch(Throwable e) {
e.printStackTrace();
throw new Error(e.getMessage());
}
}
}
で、最後に実行結果。
========================================「クラスEnhancer越しに生成したインスタンスはFooを拡張したクラスのインスタンスであり、クラスの内部でメソッドを呼んだ場合でもきちんとinterceptされる」ということですね。
<<yamo.Foo$$EnhancerByCGLIB$$ccaf9ecf>>
========================================
[yamo.Foo$$EnhancerByCGLIB$$ccaf9ecf][aaa]start Intercepter
<aaa> start
[yamo.Foo$$EnhancerByCGLIB$$ccaf9ecf][bbb]start Intercepter
<bbb> start
<bbb> end
[yamo.Foo$$EnhancerByCGLIB$$ccaf9ecf][bbb]end Intercepter
<aaa> end
[yamo.Foo$$EnhancerByCGLIB$$ccaf9ecf][aaa]end Intercepter
========================================
<<yamo.Foo>>
========================================
<aaa> start
<bbb> start
<bbb> end
<aaa> end
教訓:はてなダイアリーに載せるつもりなら「<」とか「>」の使用は避けよう