はじめに
java.lang.reflect.Proxyを利用して、指定したインターフェイスを実装したクラスに対し、そのメソッド呼び出し前後に任意の処理を追加します。こういう場面で使えるんじゃないかな?ってのがありますが、まずは簡単なサンプルを使って実際に動かしてみたいと思います。
まずはProxyを使わないで..
ISome.java
public interface ISome {
public void doSomething(int val);
}
Some.java
public class Some implements ISome {
@Override
public void doSomething(int val) {
System.out.println(val);
}
}
Main.java
public class Main {
public static void main(String[] args) {
System.out.println("start");
ISome some = new Some();
some.doSomething(1000);
System.out.println("end");
}
}
敢えて示すまでもないですが、実行結果は以下のようになります。
start
1000
end
Proxyを使ってみる..
SomeProxyクラスを追加します。
SomeProxy.java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class SomeProxy {
private ISome some;
private Object proxy;
private SomeProxy(ISome some) {
this.some = some;
this.proxy = Proxy.newProxyInstance(
ISome.class.getClassLoader(),
new Class[]{ ISome.class },
new SomeHandler());
}
/**
* 外部からはこのメソッドを通じてProxyを取得します.
*/
public static ISome createProxy(ISome some) {
SomeProxy obj = new SomeProxy(some);
return ISome.class.cast(obj.proxy);
}
/**
* Proxyのメソッド呼び出しハンドラ.
*/
private class SomeHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("before: invoke method called..");
Object o = method.invoke(some, args);
System.out.println("after: invoke method called..");
return o;
}
}
}
ISomeインターフェイスとその実装のSomeクラスに変更はありません。
呼び出し元のMainクラスを以下のように変更します。
Main.java
public class Main {
public static void main(String[] args) {
System.out.println("start");
ISome some = new Some();
some.doSomething(1000);
//Proxyを利用した呼び出しを行います
ISome proxy = SomeProxy.createProxy(some);
proxy.doSomething(2000);
System.out.println("end");
}
}
実行結果は以下のようになります。
既存のSomeクラスには全く手を加えていないのに処理が追加されました。
start
1000
before: invoke method called..
2000
after: invoke method called..
end
次回
「こういう場面で使えるんじゃないかな?」を具体的に書こうかなと思っています。