代理模式是设计模式之一。所谓“代理”即是以一个代理对象替代真正要用到的那个对象。看如下UML简图:
代理类(ProxyObj) 通过持有被代理类(RealObj) 的实例,将操作委派给 RealObj。这样做的意义是,可以在被代理对象(RealObj)被调用之前和之后做一些事情,甚至可以控制被代理对象,决定什么时候创建它,什么时候删除它。
Sample code:
class ProxyObj extends TargetObj {
private RealObj r;
public void invoke() {
if (null == r) {
r = new RealObj();
}
// do sthm before invoke
r.invoke();
// do sthm after invoke
}
public static void main(String[] args) {
TargetObj t = new ProxyObj();
t.invoke();
}
}
动态代理:
动态代理更加灵活地将方法调用定向到另一个接口-- InvovationHandler, 这是一个JDK提供的接口。它使得代理类不必与被代理类实现同样的接口或者抽象类。
Sample code of dynamic proxy:
public class ProxyHandler implements InvocationHandler {
private Object obj;
public ProxyHandler(Object o) {
this.obj = o;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
Object object;
System.out.println("Before invocation of RealObj.soSth()");
object = method.invoke(obj, args);
System.out.println("After invocation of RealObj.soSth()");
return object;
}
/* public static void main(String[] args) throws Exception {
Class clz = Interface.class;
Interface target = (Interface) Proxy.newProxyInstance(clz
.getClassLoader(), new Class[] { clz }, new ProxyHandler(
new RealObj()));
target.doSth();
}*/
}
代理是一件神奇有用的事情,假如 doSth() 方法是一个基于事务的数据库操作,那么就可以围绕着 doSth() 方法做些文章,在它之前或之后,套上事务处理。
被代理的类,必须是实现了某接口的类,若是继承自抽象类或具体类就不行,原因是 Proxy.newProxyInstance() 的参数必须有被代理类的父接口,具体可以查看 JKD 源码。