メソッドのフック
Posted feedbacks - Java
空気を読まんと投稿。 java.lang.reflectパッケージを使用します。 InvocationHandlerインタフェースのinvoke()メソッドで前処理、後処理を実装します。 Proxy.newProxyInstance() で受け取ったインスタンスのメソッドを実行したときに、 InvocationHandler.invoke()が動作します。
インタフェースに対してのみ適用可能であることをお忘れなく。
実行結果。
proxy = class test.hook.$Proxy0
method called. name = execute
ServiceImpl.execute() called.
method returned.
return value = Hello, world.
see: Proxy (Java 2 Platform SE 5.0)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | package test.hook;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class Hook {
public Hook() {
InvocationHandler handler = new TestInvocationHandler(new ServiceImpl());
Service service = (Service) Proxy.newProxyInstance(ServiceImpl.class.getClassLoader(), new Class[]{Service.class}, handler);
System.out.println("return value = " + service.execute());
}
public static void main(String[] args) {
new Hook();
}
}
/** サービスのインタフェース */
interface Service {
public String execute();
}
/** サービスの実装クラス */
class ServiceImpl implements Service {
public String execute() {
System.out.println("ServiceImpl.execute() called.");
return "Hello, world.";
}
}
/** メソッドのフックに使用するハンドラ */
class TestInvocationHandler implements InvocationHandler {
private Service service;
public TestInvocationHandler(Service service) {
this.service = service;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result;
System.out.println("proxy = " + proxy.getClass().toString());
System.out.println("method called. name = " + method.getName()); //前処理
result = method.invoke(service, args); //実際の処理
System.out.println("method returned."); //後処理
return result;
}
}
|
before/after は各 setter 経由で渡す。 なんか他の見てると、題意から外れてる気がしなくもない・・。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | public class HookSample {
private Runnable before = new Runnable() {
public void run() { }
};
private Runnable after = new Runnable() {
public void run() { }
};
public void call() {
before.run();
process();
after.run();
}
protected void process() {
System.out.println("main process...");
}
public void setBefore(Runnable r) {
if (r != null) {
before = r;
}
}
public void setAfter(Runnable r) {
if (r != null) {
after = r;
}
}
}
|
題意を、呼び側も呼ばれ側も改造する事なく、開始終了のフックを行う事と解釈しました。
アスペクト指向を Java 上で実現する AspectJ を用いてメソッドの開始と終了にフックを行うサンプルです。下記の Sample クラスの printMessage メソッドに対するフックを行います。
public class Sample {
public static void main(String[] args) {
new Sample().printMessage("Hello, world.");
}
public void printMessage(String message) {
System.out.println(message);
}
}
言語は AspectJ と言った方が良いかも知れません。
アスペクト指向を Java 上で実現する AspectJ を用いてメソッドの開始と終了にフックを行うサンプルです。下記の Sample クラスの printMessage メソッドに対するフックを行います。
public class Sample {
public static void main(String[] args) {
new Sample().printMessage("Hello, world.");
}
public void printMessage(String message) {
System.out.println(message);
}
}
言語は AspectJ と言った方が良いかも知れません。
1 2 3 4 5 6 7 8 9 10 11 12 | public aspect Trace {
pointcut message(): call(* Sample.printMessage(..));
before(): message() {
System.out.println("*** begin of printMessage() ***");
}
after(): message() {
System.out.println("*** end of printMessage() ***");
}
}
|



todogzm
#6017()
Rating0/8=0.00
例えば、あるクラスのあるメソッドを実行する前に他の処理を呼びたい(例えばログやトランザクション開始など)。 また、そのメソッドの終了後にも何らかの後処理を呼びたい(トランザクション終了など)。
そのような、メソッドに対するフック処理を書いてください。 ライブラリを使用してメソッドのフックを実現した場合は ライブラリの名前を紹介してくれると助かります。
[ reply ]