java中实现动态代理,用InvocationHandler
和Proxy
就可以了。
所谓的动态代理,就是真正执行操作的对象不是原始的对象,就像A拜托B买东西,然后B买好东西后包装好给A。
例:
void iTest() throws Exception {
Foo foo = new Foo();
IFoo obj = (IFoo) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{IFoo.class}, new MIncocationHandler(foo));
obj.say("hello world");
}
class MIncocationHandler implements InvocationHandler {
private Object realObj;
public MIncocationHandler(Object obj) {
this.realObj = obj;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("begin method invoke");
method.invoke(realObj, args);
System.out.println("after method invoke");
return proxy;
}
}
interface IFoo {
public void say(String str);
}
class Foo implements IFoo{
public void say(String str) {
System.out.println(str);
}
}
这样我们就能在不破坏原来的代码的情况下,在代码执行的前后插入日志等操作,spring的事务就是利用该原理,但是用的cglib实现的动态代理类的生成,这样就不用定义接口了,如果按照上面写的代码去实现的话是需要首先定义接口的。
备注:
反射只能得到该类本身的信息,不能得到父类或者实现的接口的信息。
接口中的变量是public static final的,方法是public的。
生成的动态代理类实现了Proxy
初始化中传入的所有接口。如果是多个接口的话,就要在handler中的invoke方法中自己判断是调用了哪一个类的方法,不能直接传递一个指定的对象了。
如果是多个接口的话,各个接口中的方法不能冲突,例如方法名称一样但是返回类型不同,这样的话实现类就不能确定该实现哪一个方法,因此会初始化代理类失败