很多框架或工具都是利用代理技术实现的。典型的如spring 的AOP、easymock、单元覆盖率检测工具等。静态代理比较好理解,就是自己写代理类来完成附加的功能,设计模式中专门有个代理模式讲这个。动态代理是指代理实现对象并不是在编译期间生成好的,而是在运行过程中产生的。这样的好处是当被代理的接口方法(注:jdk动态代理只能对接口进行代理)发生变化时,不需要改动代理实现类的代码。以下为示例代码:
假设有个接口:
public interface IDoSomething { public void doA(); //public void doB(); }
一个常规的实现类:
public class DoSomethingImpl implements IDoSomething{ @Override public void doA() { System.out.println("I'm working..."); } }
如果是静态代理,大概就写成这个样子:(静态代理通常实现和被代理类相同的接口)
public class StaticProxyDoSomething implements IDoSomething{ private IDoSomething target; public StaticProxyDoSomething(IDoSomething target){ this.target=target; } public void doA(){ System.out.println("代理准备"); target.doA(); System.out.println("代理完成"); } // public void doB(){ // // } }
可以看出,当接口方法发生变化,代理类里的方法也要跟着修改
动态代理类写成这样就可以了:
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class ProxyDoSomething implements InvocationHandler{ private Object target; public ProxyDoSomething(Object target){ this.target=target; } public Object invoke(Object proxy,Method method,Object[] args) throws Throwable{ Object result; System.out.println("准备工作..."); result=method.invoke(target,args); System.out.println("代理完成..."); return result; } }
动态代理类需要实现InvocationHandler接口,覆写invoke方法。注意invoke方法中的第一个参数“proxy”容易引起混淆,它是一个隐含实现,对编码来说并没有用到。而执行method.invoke时需要给的是被代理对象。可以看出动态代理类就这么一些内容。未来不论接口再增加、修改了什么,代理类都不需要改写了。而且是执行被代理对象的每种接口方法都会调用这里的invoke,这就为我们提供一个方便的途径来进行“全局控制”,比如记录日志、权限检查什么的。
最后是一个简单的测试类:
import java.lang.reflect.Proxy; public class TestProxy { public static void main(String[] args){ DoSomethingImpl dsi=new DoSomethingImpl(); IDoSomething proxy=(IDoSomething)Proxy.newProxyInstance(dsi.getClass().getClassLoader(), dsi.getClass().getInterfaces(),new ProxyDoSomething(dsi)); proxy.doA(); } }