Edited at

java.lang.reflect.Proxyの使い方(1)

More than 3 years have passed since last update.


はじめに

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


次回

「こういう場面で使えるんじゃないかな?」を具体的に書こうかなと思っています。