动态代理

动态代理是代理模式的补充,传统的代理模式要求我们为代理类创建class文件(.java文件编译后的字节流),相对麻烦,动态代理可以省去这个步骤,在运行时生成和class文件等价的字节流,然后加载到JVM中。本文参考了http://www.jianshu.com/p/6f6bb2f0ece9# ,在他之上增加了类图和自己的理解。

老规矩,向上一张类图。

类图

DynamicProxy.png

实例

public class Main {

    public static void main(String args[]) {
        Subject realSubject = new RealSubject();  //创建委托对象
        ProxyHandler proxyHandler = new ProxyHandler(realSubject);  //创建InvocationHandler对象
        Subject proxy = (Subject)      Proxy.newProxyInstance(realSubject.getClass().getClassLoader()
                , realSubject.getClass().getInterfaces()
                , proxyHandler);  //生成代理对象
        
        proxy.request();   //使用代理对象
    }
}

interface Subject {
    public void request();
}

class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("real request");
    }
    
}

class ProxyHandler implements InvocationHandler{
    private Subject subject;
    public ProxyHandler(Subject subject){
        this.subject = subject;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) //proxy就是生成的代理对象
            throws Throwable {
        System.out.println("====before====");  //定义预处理的工作,当然你也可以根据 method的不同进行不同的预处理工作
        Object result = method.invoke(subject, args);
        System.out.println("====after====");
        return result;
    }
}
------------------------------输出---------------------------------------
====before====
real request
====after====

结合类图,我们首先创建一个RealSubject对象,一个ProxyHandler对象,这个对象的类继承自InvocationHandler,invoke(Object proxy, Method method, Object[] args)第一个参数proxy就是由反射创建的代理对象,第二参数表明代理对象调用的方法,第三个参数表示调用的参数,在这个方法里我们调用了realSubject的对应的方法,在之前和之后我们都可以做相应的操作,这正是代理的含义。那个这个invoke(Object proxy, Method method, Object[] args)是什么时候调用的?答案是proxy.request();这个方法是自动生成的,内部实现类似

public final class $Proxy1 extends Proxy implements Subject{
   private InvocationHandler h;
   private $Proxy1(){}
   public $Proxy1(InvocationHandler h){
       this.h = h;
   }
   public int request(int i){
       Method method = Subject.class.getMethod("request", new Class[]{int.class});    //创建method对象
       return (Integer)h.invoke(this, method, new Object[]{new Integer(i)}); //调用了invoke方法
   }
}

这个方法将代理对象作为参数传递给InvocationHandler.invoke方法。所以调用链如下:proxy.request()--->InvocationHandler.invoke()。再结合类图就不难理解。

参考

http://www.jianshu.com/p/6f6bb2f0ece9#

你可能感兴趣的:(动态代理)