首先推荐一篇别人写的关于代理的博客,写的很清楚 http://langyu.iteye.com/blog/410071
InvocationHandler 字面意思 就是 调用的处理者。 所以当代理类调用某个被代理的方法时,就会自动调用“调用处理者”的invoke()方法。
每个代理对象,都有一个与之关联的InvocationHandler。
======================================================
/*
* 想要重写String类型的toString方法,但发现String是final类型,不能被继承
* 里面的toString也不能被重写啊。 可是使用动态代理就能实现重写。
*/
package com.Test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
class StringProxy implements InvocationHandler {
private Object o;//委托对象,就是要“被代理”的对象
private String methodName;
public Object bind(Object obj, String methodName) {// 被代理的对象和方法
this.o = obj;
this.methodName = methodName;
//得到代理类
return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj
.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] obj)
throws Throwable {
if (method.getName().equals(methodName)) {
Object result = method.invoke(o, obj); //注意此处是用o去调用,就是用委托类的逻辑去调用
return "[proxy:"+result+"]";
} else {
Object result = method.invoke(o, obj);
return result;
}
}
}
public class ProxyTest {
public static void main(String[] args) {
StringProxy proxy = new StringProxy();
String str = "aa";
CharSequence strProxy = (CharSequence)proxy.bind(str, "toString");
System.out.println(strProxy.toString());
}
}
其实要写代理还可以写的更加简单,如下面的代码用来代理一个实现了List接口的对象。所实现的功能也非常简单,那就是禁止使用List接口中的add方法。如果在getList中传入一个实现List接口的对象,那么返回的实际就是一个代理对象,尝试在该对象上调用add方法就会抛出来异常。 代码如下:
public List getList(final List list) {
return (List) Proxy.newProxyInstance(DummyProxy.class.getClassLoader(), new Class[] { List.class },
new InvocationHandler() { //匿名内部类,代码更加简洁清爽
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("add".equals(method.getName())) {
throw new UnsupportedOperationException();
}
else {
return method.invoke(list, args); //使用正常的list的逻辑。 被代理的是list 或者说委托对象是list
}
}
});
}