JAVA动态代理模式源码解析

来源:互联网 发布:如何上淘宝一千零一夜 编辑:程序博客网 时间:2024/06/05 08:20

动态代理:代理类在运行时生成,即java在编译完之后并没有实际的class文件,而是在运行时生成类字节码,并加载到JVM中。

实现动态代理的步骤:

1、定义一个公共接口,一个目标类,目标类实现公共接口。

2、自己定义一个类,即调用处理器类,实现InvocationHandler接口,代理类调用任何方法都会经过这个调用处理类

3、生成代理对象,调用Proxy.newProxyInstance()方法,需要三个参数,分别为目标类的类加载器、实现的一系列接口和调用处理器实例。

下面写个简单的demo分析它的实现原理

//代理类和目标类的公共接口public interface TrainTicketSale {    void sellTickets();}//目标类public class TrainStationSale implements TrainTicketSale {    @Override    public void sellTickets() {        System.out.println("火车站出售火车票");    }}//处理器类public class TrainTicketHandler implements InvocationHandler{   private TrainTicketSale realSubject;    public TrainTicketHandler(TrainTicketSale target){      //传入目标类对象          this.realSubject=target;    }    @Override    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {            System.out.println("--------- before---------");      //反射调用目标类方法         Object result=method.invoke(realSubject,objects);        System.out.println("--------- after---------");        return result;    }}//测试Testpublic class MyClassTest {    public static void main(String[] args){         TrainTicketSale stationSale=new TrainStationSale();        TrainTicketHandler handler=new TrainTicketHandler(stationSale);        TrainTicketSale proxy = (TrainTicketSale) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), stationSale.getClass().getInterfaces(), handler);          proxy.sellTickets();    }}//控制台打印结果 com.intellij.rt.execution.application.AppMain com.example.MyClassTest--------- before---------火车站出售火车票--------- after--------

现在来分析下动态代理的执行流程

/***loader 类加载器*interfaces 目标实现接口* h 处理器实现类*/public static Object newProxyInstance(ClassLoader loader,                                          Class<?>[] interfaces,                                          InvocationHandler h)        throws IllegalArgumentException    {        if (h == null) {            throw new NullPointerException();        }        /*         * 获取代理类对象         */        Class<?> cl = getProxyClass0(loader, interfaces);        /*         * 调用代理类构造方法         */        try {            final Constructor<?> cons = cl.getConstructor(constructorParams);            return newInstance(cons, h);        } catch (NoSuchMethodException e) {            throw new InternalError(e.toString());        }    }

再看下getProxyClass0加载类的这个方法

private static Class<?> getProxyClass0(ClassLoader loader,                                           Class<?>... interfaces) {  // 接口实现的方法超过最大方法数,抛出异常        if (interfaces.length > 65535) {            throw new IllegalArgumentException("interface limit exceeded");        }        Class<?> proxyClass = null;    //收集接口名作为代理类缓存的key        String[] interfaceNames = new String[interfaces.length];        // 检测重复的接口名字         Set<Class<?>> interfaceSet = new HashSet<>();        for (int i = 0; i < interfaces.length; i++) {            String interfaceName = interfaces[i].getName();            Class<?> interfaceClass = null;            try {              //加载目标类实现接口到内存                interfaceClass = Class.forName(interfaceName, false, loader);            } catch (ClassNotFoundException e) {            }            if (interfaceClass != interfaces[i]) {                throw new IllegalArgumentException(                    interfaces[i] + " is not visible from class loader");            }           //....省略无关紧要代码        }      //将目标接口名数组作为key   List<String> key = Arrays.asList(interfaceNames);        /*         * 使用classLoader查找或者创建代理类缓存         */        Map<List<String>, Object> cache;        synchronized (loaderToCache) {            cache = loaderToCache.get(loader);            if (cache == null) {                cache = new HashMap<>();                loaderToCache.put(loader, cache);            }        }     synchronized (cache) {            do {                Object value = cache.get(key);                if (value instanceof Reference) {                    proxyClass = (Class<?>) ((Reference) value).get();                }                if (proxyClass != null) {                    // 缓存中已经有代理类,直接返回                    return proxyClass;                } else if (value == pendingGenerationMarker) {                    // proxy class being generated: wait for it                    try {                        cache.wait();                    } catch (InterruptedException e) {                        /*                         * The class generation that we are waiting for should                         * take a small, bounded time, so we can safely ignore                         * thread interrupts here.                         */                    }                    continue;                } else {                    /*                     * No proxy class for this list of interfaces has been                     * generated or is being generated, so we will go and                     * generate it now.  Mark it as pending generation.                     */                    cache.put(key, pendingGenerationMarker);                    break;                }            } while (true);        }      synchronized (nextUniqueNumberLock) {                    num = nextUniqueNumber++;                }                String proxyName = proxyPkg + proxyClassNamePrefix + num;                //关键代码,调用底层的native方法生成代理类                proxyClass = generateProxy(proxyName, interfaces, loader, methodsArray,                        exceptionsArray);            }            // add to set of all generated proxy classes, for isProxyClass            proxyClasses.put(proxyClass, null);        } finally {             //生成之后通过弱引用保存到cache中            synchronized (cache) {                if (proxyClass != null) {                    cache.put(key, new WeakReference<Class<?>>(proxyClass));                } else {                    cache.remove(key);                }                cache.notifyAll();            }        }        return proxyClass;    }

底层生成代理类后,再调用它的newInstance()方法

  private static Object newInstance(Constructor<?> cons, InvocationHandler h) {        try {            return cons.newInstance(new Object[] {h} );        } catch (IllegalAccessException | InstantiationException e) {            throw new InternalError(e.toString());        } catch (InvocationTargetException e) {            Throwable t = e.getCause();            if (t instanceof RuntimeException) {                throw (RuntimeException) t;            } else {                throw new InternalError(t.toString());            }        }    }

构造方法传入InvocationHandler的实现类对象,那么这个handler对象传进去到底是干嘛使的呢?我们可以看下系统帮我们生成的代理类是什么样子的,我们用反编译工具打开硬盘中的代理类。

import com.example.TrainTicketSale;  import java.lang.reflect.*;  public final class $Proxy11 extends Proxy      implements TrainTicketSale  {      // 构造方法,参数就是刚才传过来的MyInvocationHandler类的实例      public $Proxy11(InvocationHandler invocationhandler)      {          super(invocationhandler);      }      public final boolean equals(Object obj)      {          try          {              return ((Boolean)super.h.invoke(this, m1, new Object[] {                  obj              })).booleanValue();          }          catch(Error _ex) { }          catch(Throwable throwable)          {              throw new UndeclaredThrowableException(throwable);          }      }      /**      * 这个方法是关键部分      */      public final void sellTickets()      {          try          {              // 实际上就是调用TrainTicketHandler的public Object invoke(Object proxy, Method method, Object[] args)方法              super.h.invoke(this, m3, null);              return;          }          catch(Error _ex) { }          catch(Throwable throwable)          {              throw new UndeclaredThrowableException(throwable);          }      }      public final int hashCode()      {          try          {              return ((Integer)super.h.invoke(this, m0, null)).intValue();          }          catch(Error _ex) { }          catch(Throwable throwable)          {              throw new UndeclaredThrowableException(throwable);          }      }      public final String toString()      {          try          {              return (String)super.h.invoke(this, m2, null);          }          catch(Error _ex) { }          catch(Throwable throwable)          {              throw new UndeclaredThrowableException(throwable);          }      }      private static Method m1;      private static Method m3;      private static Method m0;      private static Method m2;      // 在静态代码块中获取了4个方法:Object中的equals方法、TrainTicketSale中的sellTickets方法、Object中的hashCode方法、Object中toString方法      static       {          try          {              m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] {                  Class.forName("java.lang.Object")              });              m3 = Class.forName("com.example.TrainTicketSale").getMethod("sellTickets", new Class[0]);              m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);              m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);          }          catch(NoSuchMethodException nosuchmethodexception)          {              throw new NoSuchMethodError(nosuchmethodexception.getMessage());          }          catch(ClassNotFoundException classnotfoundexception)          {              throw new NoClassDefFoundError(classnotfoundexception.getMessage());          }      }  }  

可以看出,代理类实现了目标类的接口,并保存了接口中每个Method对象,当代理类调用接口方法时,都会调用到h.invoke()方法。

参考链接:

代理模式及Java实现动态代理

JDK动态代理实现原理

原创粉丝点击