LoginSignup
41
36

More than 5 years have passed since last update.

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

Last updated at Posted at 2014-09-27

はじめに

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

次回

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

41
36
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
41
36