代理模式是设计模式之一。所谓“代理”即是以一个代理对象替代真正要用到的那个对象。看如下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 源码。