很多框架或工具都是利用代理技术实现的。典型的如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();
}
}
转载于:https://blog.51cto.com/6738767/1396690