Dynamic Proxy

Dynamic Proxyの例。

COR(Chain Of Responsibility)パターンと組み合わせて、インタセプターを実現すれば
AOPのような効果を比較的簡単に得ることが出来ます。

個人的にはフレームワークや汎用的なライブラリを組むときには結構使えると思います。

まずはinterface。


/*
* @author shot
*
*/
package org.shotd.dev.local.dynamicproxy;

/**
* @author shot
*
*/
public interface Hoge {

public void say();

}

次に具象クラス(って言い方も最近しないのかな)


/*
* @author shot
*
*/
package org.shotd.dev.local.dynamicproxy;

/**
* @author shot
*
*/
public class HogeImpl implements Hoge {

/*
* @see org.shotd.dev.local.dynamicproxy.Hoge#say()
*/
public void say() {
System.out.println("hello");
}

}

肝なProxyクラスはオブジェクトごと渡すやつと、名前でひくやつとメソッドを両方用意。
invokeメソッドは、実際にオブジェクトのメソッドが実行されたときに代わりにこちらが実行される。


/*
* @author shot
*
*/
package org.shotd.dev.local.dynamicproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
* @author shot
*
*/
public class HogeProxy implements InvocationHandler {

private Object obj;

private HogeProxy(Object obj){
this.obj = obj;
}

public static Object newInstance(Object o){
return Proxy.newProxyInstance(o.getClass().getClassLoader(),
o.getClass().getInterfaces(), new HogeProxy(o));
}

public static Object newInstanceByName(String str)
throws ClassNotFoundException, InstantiationException, IllegalAccessException{

Class clazz = Class.forName(str);
Object o = clazz.newInstance();

return Proxy.newProxyInstance(o.getClass().getClassLoader(),
o.getClass().getInterfaces(), new HogeProxy(o));
}


/*
* @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object,
* java.lang.reflect.Method, java.lang.Object[])
*/
public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable {

try{
System.out.println("before");
return m.invoke(obj, args);
}finally{
System.out.println("after");
}

}

}

んで、mainを用意。


/*
* @author shot
*
*/
package org.shotd.dev.local.dynamicproxy;

/**
* @author shot
*
*/
public class DynamicProxyMain {

public static void main(String[] args) throws Exception{

Hoge hoge = (Hoge)HogeProxy.newInstance(new HogeImpl());
hoge.say();

/* better way */
Hoge hoge2 =
(Hoge)HogeProxy.newInstanceByName("org.shotd.dev.local.dynamicproxy.HogeImpl");

hoge2.say();

}
}

んじゃ、実行!!!


before
hello
after
before
hello
after

はい。きちんと出ました。
でも、このままだと対象のインタフェースのどのメソッドでも、このDynamicProxyの
餌食になってしまいます。なんだかSpringのやたらめったらAOPみたいですね(^^;)

んーinvokeメソッドの中で、条件で判断させるしかないのかなあ〜。