您好,欢迎访问代理记账网站
移动应用 微信公众号 联系我们

咨询热线 -

电话 15988168888

联系客服
  • 价格透明
  • 信息保密
  • 进度掌控
  • 售后无忧

JavaBase-Java反射机制-动态代理-jdk动态代理(源码)

JavaBase-Java反射机制

反射的应用:动态代理

动态代理概述

  • 代理设计模式的原理:
    • 使用一个代理将对象包装起来,然后用该代理对象代替原始对象。任何对原始对象的调用都要通过代理对象操作。代理对象决定是否以及何时将方法调用转到原始对象上
  • 静态代理:
    • 特征是代理类和目标对象的类都是在编译期间确定下来,不利于程序的扩展。同时,每一个代理类只能为一个接口服务,这样导致程序开发中必然产生过多的代理类。理想的方式是,通过一个代理类完成完全的代理功能。
  • 动态代理是指客户通过代理类来调用其他对象的方法,并且是在程序运行时根据需要动态创建目标类的代理对象。
  • 动态代理适用场合:
    • 调试
    • 远程方法调用
  • 动态代理相比于静态代理的有点:
    • 抽象角色中(接口)声明的所有方法都被转移到调用处理器一个集中的方法中处理,这样,可以更加灵活和统一的处理众多的方法

动态代理的例子

静态代理

  • 步骤

    • 创建一个被接口类ClothFactory,定义所需要代理的方法
    • 创建被代理类MyClothFactory实现接口ClothFactory
    • 创建被代理类ProxyClothFactory实现接口ClothFactory
    • 在代理类中,添加代理类MyClothFactory的属性 ,作为后续从代理类控制何时调用被代理类
    • 在代理类中,添加给代理类属性赋值的方法
    • 在代理类的代理方法中,通过被代理类的属性调用被代理类的方法
  • 代码

    • package com.jl.java.base.proxy;
      
      /**
       * 静态代理
       * 特点:代理类和被代理类在编译期间,就确定下来了
       * @author jiangl
       * @version 1.0
       * @date 2021/5/7 15:14
       */
      
      /**
       * 1.创建一个接口,使得代理类和被代理类都实现这个接口,创建一个被接口类ClothFactory,定义所需要代理的方法
       */
      interface ClothFactory{
          void produceCloth();
      }
      
      /**
       * 2.创建被代理类MyClothFactory实现接口ClothFactory
       */
      class MyClothFactory implements ClothFactory{
      
          @Override
          public void produceCloth() {
              System.out.println("生产衣服");
          }
      }
      
      
      /**
       * 3.创建被代理类ProxyClothFactory实现接口ClothFactory
       */
      class ProxyClothFactory implements ClothFactory{
      
          /**
           * 4.在代理类中,添加代理类MyClothFactory的属性 ,作为后续从代理类控制何时调用被代理类
           */
          private ClothFactory myClothFactory;
      
          /**
           * 5.在代理类中,添加给代理类属性赋值的方法
           * @param myClothFactory
           */
          public ProxyClothFactory(MyClothFactory myClothFactory) {
              this.myClothFactory = myClothFactory;
          }
      
          /**
           * 6.在代理类的代理方法中,通过被代理类的属性调用被代理类的方法
           */
          @Override
          public void produceCloth() {
              System.out.println("获取原料");
              myClothFactory.produceCloth();
              System.out.println("完成");
          }
      }
      
      public class StaticProxyTest {
      
          public static void main(String[] args) {
              ClothFactory proxyClothFactory = new ProxyClothFactory(new MyClothFactory());
              proxyClothFactory.produceCloth();
          }
      }
      
  • 静态代理缺点

    • 在编译期,就确定了代理类和被代理类,如果大量使用会导致系统中存在很多代理类

动态代理(JDK动态代理)

  • 创建一个被接口类Human,定义所需要代理的方法,代理类和被代理类都要实现这个方法

  • 创建一个被代理类Student实现Human接口,并重写接口中的方法

  • 通过Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)方法,生成代理类

    • ClassLoader loader:被代理类的类加载器,用于通过类加载器动态创建一个代理类
    • Class<?>[] interfaces:被代理类所实现的所有接口数组,因为被代理类可能实现多个接口所以是数组。而代理类需要通过实现这些接口来,并重写接口中的方法来代理被代理类。
    • InvocationHandler h:回调方法对象,代理类通过回调方法对象中的 invoke方法来实现对被代理类的调用和功能的增强(可以在invoke(Object proxy, Method method, Object[] args)中编写所要对被代理类功能增强的代码逻辑)
      • Object proxy:这是代理类的对象
      • Method method:这是所要代理的方法
      • Object[] args:所要代理方法的入参数组
    • 在InvocationHandler h类中需要添加一个被代理类的属性(为了通用性该属性的类型应为Object),用于在invoke()方法中,通过Method.invoke方法来调用被代理类的所需要代理的方法
  • 最后先创建一个被代理类对象

    • 通过Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)方法获取到代理类的对象,该对象可以赋值给Human proxy(向上转型,类的多态性)
      • Human proxy = Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h);
    • 通过调用代理类对象proxy.eat()调用被代理类的方法,实现代理模式
  • 代码

    • package com.jl.java.base.proxy;
      
      import org.junit.Test;
      
      import java.lang.reflect.InvocationHandler;
      import java.lang.reflect.Method;
      import java.lang.reflect.Proxy;
      
      /**
       * @author jiangl
       * @version 1.0
       * @date 2021/5/7 15:19
       */
      interface Human{
          String getBelief();
      
          void eat(String food);
      }
      
      /**
       * 被代理类
       */
      class Student implements Human{
      
          @Override
          public String getBelief() {
              System.out.println("好好学习,天天向上");
              return "学习";
          }
      
          @Override
          public void eat(String food) {
              System.out.println("吃有营养的东西");
          }
      }
      
      /**
       * 要想实现动态代理,需要解决的问题?
       * 问题一:如何根据加载到内存中的被代理类,动态的创建一个代理类及其对象
       * 问题二:当通过代理类的对象调用方法时,如何动态的去调用被代理类中的同名方法
       */
      
      class ProxyFactory{
          /**
           * 调用此方法,返回一个代理类的对象,解决问题一
           * @param obj 被代理类的对象
           * @return 返回代理类的对象
           */
          public static Object getProxyInstance(Object obj){
              MyInvocationHandler handler = new MyInvocationHandler();
              handler.bind(obj);
              return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
                      obj.getClass().getInterfaces(),
                      handler);
          }
      }
      
      class MyInvocationHandler implements InvocationHandler{
      
          /**
           * 需要使用被代理类的对象进行赋值
           */
          private Object obj;
      
          public void bind(Object obj){
              this.obj = obj;
          }
      
          /**
           * 当通过代理类的对象,调用方法a时,就会自动的调用如下的方法
           * 将被代理类要执行的方法a的功能就声明在invoke()中
           * @param proxy 代理类的对象
           * @param method 代理类对象调用的方法,此方法也就作为了被代理类对象要调用的方法
           * @param args 方法的入参
           * @return
           * @throws Throwable
           */
          @Override
          public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
              System.out.println("---代理---");
              //obj:被代理类对象
              Object returnValue = method.invoke(obj, args);
              //上述方法的返回值,就作为当前类的invoke()的返回值
              return returnValue;
          }
      }
      public class DynamicProxyTest {
      
          @Test
          public void test(){
              Object proxyInstance1 = ProxyFactory.getProxyInstance(new Student());
              System.out.println(proxyInstance1.getClass());
              Class<?>[] interfaces = proxyInstance1.getClass().getInterfaces();
              for(Class inter : interfaces){
                  System.out.println(inter);
              }
              Human proxyInstance = (Human) ProxyFactory.getProxyInstance(new Student());
              proxyInstance.getBelief();
              proxyInstance.eat("苹果");
          }
      }
      

源码解析(JDK动态代理)

  • 前提:

    • 通过Proxy.nexProxyInstance()方法创建的类,实际是实现了被代理类接口,并且继承与Proxy类的如$Proxy0匿名类

    • 代码

    • @Test
      public void test(){
          Object proxyInstance1 = ProxyFactory.getProxyInstance(new Student());
          System.out.println(proxyInstance1.getClass());
          System.out.println(proxyInstance1.getClass().getSuperclass());
          Class<?>[] interfaces = proxyInstance1.getClass().getInterfaces();
          for(Class inter : interfaces){
              System.out.println(inter);
          }
      }
      
    • 结果

      • class com.jl.java.base.proxy.$Proxy5
        class java.lang.reflect.Proxy
        interface com.jl.java.base.proxy.Human
  • 源码:

    • 生成代理类源码newProxyInstance()方法

    • 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);
              final InvocationHandler ih = h;
              SecurityManager sm = System.getSecurityManager();
              if (sm != null && java.lang.reflect.Proxy.ProxyAccessHelper.needsNewInstanceCheck(cl)) {
                  return AccessController.doPrivileged(new PrivilegedAction<Object>() {
                      public Object run() {
                          return newInstance(cons, ih);
                      }
                  });
              } else {
                  return newInstance(cons, ih);
              }
          } catch (NoSuchMethodException e) {
              throw new InternalError(e.toString());
          }
      }
      
  • 在newProxyInstance()方法中,通过getProxyClass0(loader,interfaces)方法生成匿名代理类

    • 通过Java安全器检测

      • //Java安全器检测
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            final int CALLER_FRAME = 3; // 0: Reflection, 1: getProxyClass0 2: Proxy 3: caller
            final Class<?> caller = Reflection.getCallerClass(CALLER_FRAME);
            final ClassLoader ccl = caller.getClassLoader();
            checkProxyLoader(ccl, loader);
            ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
        }
        
    • 判断代理类的实现接口是否超过了int最大值,如果超过则抛出异常IllegalArgumentException

      • //判断被代理类的接口是否超过int最大值
        if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }
        
    • 创建一个代理类的变量Class proxyClass用于返回

      • //代理类 变量
        Class proxyClass = null;
        
    • 获取被代理类的所有接口(接口数组),将这些接口名作为代理类缓存的key。用于再次获取时不需要二次创建,优化性能

      • //获取所有的接口名称用于作为代理类缓存的关键字
        String[] interfaceNames = new String[interfaces.length];
        //创建一个被代理类接口的HashSet用于去重
        Set 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");
            }
        
            //校验加载得到的接口类是否真实为接口
            if (!interfaceClass.isInterface()) {
                throw new IllegalArgumentException(
                        interfaceClass.getName() + " is not an interface");
            }
        
            //判断是否有重复接口
            if (interfaceSet.contains(interfaceClass)) {
                throw new IllegalArgumentException(
                        "repeated interface: " + interfaceClass.getName());
            }
            interfaceSet.add(interfaceClass);
        
            interfaceNames[i] = interfaceName;
        }
        
    • 将接口数组转换成List,作为key

      • //将接口名字符数组转换成List<String>
        /**
         * 使用代理接口的字符串表示作为代理类缓存中的键(而不是它们的类对象)就足够了,
         * 因为我们要求代理接口通过提供的类加载器按名称进行解析,它的优点是,使用类的字符串表示会导致对类的隐式弱引用。
         */
        Object key = Arrays.asList(interfaceNames);
        
    • 根据类加载器在缓存loaderToCache map中查询,这个类加载下的所有代理类的Map

      • WeakHashMap<ClassLoader,HashMap<List,Object>>

      • //通过类加载器找到或创建一个代理类缓存
        Map cache;
        synchronized (loaderToCache) {
            //根据类加载器找到一个缓存Map
            cache = (Map) loaderToCache.get(loader);
            //如果类加载器的缓存map不存在,则重新创建
            if (cache == null) {
                cache = new HashMap();
                loaderToCache.put(loader, cache);
            }
            /**
             * 此映射将在此方法期间保持有效,无需进一步同步,因为只有在类装入器变得不可访问时才会删除映射。
             */
        }
        
    • 获取的到代理类map中根据,接口数组key查询获取代理类,此处有三种情况

      • 根据key查询到代理类,直接返回

      • 根据key获取到对象pendingGenerationMarker,表示代理类正在创建中,调用cache.await()方法进入等待

      • 根据key获取到null,则表示未创建代理,此时先将key的value赋值成pendingGenerationMarker,防止多次创建,保证线程安全,其他线程来访问则会进入上一个分支,进入等待(而正真的创建代理类,在后续逻辑中)

      • /**
         * 使用键在代理类缓存中查找接口列表。此查找将导致三种可能的值之一:
         *  null:类加载器中的接口列表当前没有代理类
         *  the pendingGenerationMarker object: 当前正在生成接口列表的代理类
         *  a weak reference to a Class object: 接口列表的代理类已经生成。
         */
        synchronized (cache) {
            /**
             * 请注意,我们不必担心在map中清除弱引用条目的缓存,
             * 因为如果代理类已被垃圾收集,则其类装入器也将被垃圾收集,
             * 因此这个缓存在GC后从整个代理类加载器缓存Map中清除
             */
            do {
                //从缓存中根据接口字符串做的关键字key获取代理类
                Object value = cache.get(key);
                //判断如果获取到的值是Reference类的对象,则调用Reference对象中的get()方法获取,引用的实际对象
                if (value instanceof Reference) {
                    proxyClass = (Class) ((Reference) value).get();
                }
                //判断代理类
                if (proxyClass != null) {
                    //代理类已创建,返回代理类
                    return proxyClass;
                } else if (value == pendingGenerationMarker) {
                    // 代理类正在创建中,进入wait()等待
                    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 {
                    /**
                     * 尚未生成或正在生成此接口列表的代理类,因此我们将立即生成它。将其标记为挂起生成。
                     * 这样做的目的是,多线程情况下,其他线程会看到一个正在创建的标识,进入上一个if条件,进入等待
                     */
                    cache.put(key, pendingGenerationMarker);
                    break;
                }
            } while (true);
        }
        
    • 创建代理类对象步骤

      • 判断被代理类的接口是否都在同一个包名下,校验不通过在抛异常返回

      • /**
         * 记录非公共代理接口的包,以便在同一个包中定义代理类。
         * 验证所有非公共代理接口是否在同一个包中。
         */
        for (int i = 0; i < interfaces.length; i++) {
            int flags = interfaces[i].getModifiers();
            if (!Modifier.isPublic(flags)) {
                String name = interfaces[i].getName();
                int n = name.lastIndexOf('.');
                String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
                if (proxyPkg == null) {
                    proxyPkg = pkg;
                } else if (!pkg.equals(proxyPkg)) {
                    throw new IllegalArgumentException(
                            "non-public interfaces from different packages");
                }
            }
        }
        
      • 生成一个代理类的名称,规则是 包名+jdk代理类前缀$Proxy+计数

      • //生成一个代理类的名称,规则是 包名+jdk代理类前缀$Proxy+计数
        long num;
        synchronized (nextUniqueNumberLock) {
            num = nextUniqueNumber++;
        }
        String proxyName = proxyPkg + proxyClassNamePrefix + num;
        
      • 调用 ProxyGenerator.generateProxyClass方法生成代理类文件

      • //生成一个代理类文件
        byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, interfaces);
        
      • 通过类加载器,代理类名,代理类文件,生成一个代理类的类对象

      • try {
            //通过类加载器,代理类名,代理类文件,生成一个代理类的类对象
            proxyClass = defineClass0(loader, proxyName,
                    proxyClassFile, 0, proxyClassFile.length);
        } catch (ClassFormatError e) {
            /*
             * A ClassFormatError here means that (barring bugs in the
             * proxy class generation code) there was some other
             * invalid aspect of the arguments supplied to the proxy
             * class creation (such as virtual machine limitations
             * exceeded).
             */
            throw new IllegalArgumentException(e.toString());
        }
        
      • 将代理类添加到proxyClasses Map中,用于isProxyClass方法中使用,判断类是否为代理类

      • //将代理类添加到proxyClasses Map中,用于isProxyClass方法中使用,判断类是否为代理类
        // add to set of all generated proxy classes, for isProxyClass
        proxyClasses.put(proxyClass, null);
        
    • 最后在fianlly代码块中做最后的处理,将之前设置的缓存key,根据是否正确生成代理做最后赋值

      • 如果代理类创建成功,则创建一个弱引用WeakReference把代理类对象引用,把弱引用作为value赋值给接口名数组的key

      • 如果代理类创建失败,则删除key

      • 最后唤醒所有等待队列中的线程

      • /**
         * 我们必须以某种方式清除代理类缓存项的“挂起的生成”状态。
         * 如果成功生成了代理类,则将其存储在缓存中(使用弱引用);否则,请删除保留项。
         * 在所有情况下,都要通知此缓存中保留项的所有等待队列中的线程。
         */
        synchronized (cache) {
            if (proxyClass != null) {
                //代理类创建成功
                //根据接口数组 作为key,将代理类封装成一个索引用放入缓存map中
                cache.put(key, new WeakReference(proxyClass));
            } else {
                //代理类创建失败,则在缓存中删除key
                cache.remove(key);
            }
            //唤醒其他等待的线程,
            cache.notifyAll();
        }
        
    • 源码

      • private static Class<?> getProxyClass0(ClassLoader loader,
                                               Class<?>... interfaces) {
            //Java安全器检测
            SecurityManager sm = System.getSecurityManager();
            if (sm != null) {
                final int CALLER_FRAME = 3; // 0: Reflection, 1: getProxyClass0 2: Proxy 3: caller
                final Class<?> caller = Reflection.getCallerClass(CALLER_FRAME);
                final ClassLoader ccl = caller.getClassLoader();
                checkProxyLoader(ccl, loader);
                ReflectUtil.checkProxyPackageAccess(ccl, interfaces);
            }
            //判断被代理类的接口是否超过int最大值
            if (interfaces.length > 65535) {
                throw new IllegalArgumentException("interface limit exceeded");
            }
            //代理类 变量
            Class proxyClass = null;
        
            //获取所有的接口名称用于作为代理类缓存的关键字
            String[] interfaceNames = new String[interfaces.length];
            //创建一个被代理类接口的HashSet用于去重
            Set 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");
                }
        
                //校验加载得到的接口类是否真实为接口
                if (!interfaceClass.isInterface()) {
                    throw new IllegalArgumentException(
                            interfaceClass.getName() + " is not an interface");
                }
        
                //判断是否有重复接口
                if (interfaceSet.contains(interfaceClass)) {
                    throw new IllegalArgumentException(
                            "repeated interface: " + interfaceClass.getName());
                }
                interfaceSet.add(interfaceClass);
        
                interfaceNames[i] = interfaceName;
            }
        
            //将接口名字符数组转换成List<String>
            /**
             * 使用代理接口的字符串表示作为代理类缓存中的键(而不是它们的类对象)就足够了,
             * 因为我们要求代理接口通过提供的类加载器按名称进行解析,它的优点是,使用类的字符串表示会导致对类的隐式弱引用。
             */
            Object key = Arrays.asList(interfaceNames);
        
            //通过类加载器找到或创建一个代理类缓存
            Map cache;
            synchronized (loaderToCache) {
                //根据类加载器找到一个缓存Map
                cache = (Map) loaderToCache.get(loader);
                //如果类加载器的缓存map不存在,则重新创建
                if (cache == null) {
                    cache = new HashMap();
                    loaderToCache.put(loader, cache);
                }
                /**
                 * 此映射将在此方法期间保持有效,无需进一步同步,因为只有在类装入器变得不可访问时才会删除映射。
                 */
            }
        
            /**
             * 使用键在代理类缓存中查找接口列表。此查找将导致三种可能的值之一:
             *  null:类加载器中的接口列表当前没有代理类
             *  the pendingGenerationMarker object: 当前正在生成接口列表的代理类
             *  a weak reference to a Class object: 接口列表的代理类已经生成。
             */
            synchronized (cache) {
                /**
                 * 请注意,我们不必担心在map中清除弱引用条目的缓存,
                 * 因为如果代理类已被垃圾收集,则其类装入器也将被垃圾收集,
                 * 因此这个缓存在GC后从整个代理类加载器缓存Map中清除
                 */
                do {
                    //从缓存中根据接口字符串做的关键字key获取代理类
                    Object value = cache.get(key);
                    //判断如果获取到的值是Reference类的对象,则调用Reference对象中的get()方法获取,引用的实际对象
                    if (value instanceof Reference) {
                        proxyClass = (Class) ((Reference) value).get();
                    }
                    //判断代理类
                    if (proxyClass != null) {
                        //代理类已创建,返回代理类
                        return proxyClass;
                    } else if (value == pendingGenerationMarker) {
                        // 代理类正在创建中,进入wait()等待
                        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 {
                        /**
                         * 尚未生成或正在生成此接口列表的代理类,因此我们将立即生成它。将其标记为挂起生成。
                         * 这样做的目的是,多线程情况下,其他线程会看到一个正在创建的标识,进入上一个if条件,进入等待
                         */
                        cache.put(key, pendingGenerationMarker);
                        break;
                    }
                } while (true);
            }
        
            //开始生产代理类
            try {
                String proxyPkg = null;    // package to define proxy class in
        
                /**
                 * 记录非公共代理接口的包,以便在同一个包中定义代理类。
                 * 验证所有非公共代理接口是否在同一个包中。
                 */
                for (int i = 0; i < interfaces.length; i++) {
                    int flags = interfaces[i].getModifiers();
                    if (!Modifier.isPublic(flags)) {
                        String name = interfaces[i].getName();
                        int n = name.lastIndexOf('.');
                        String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
                        if (proxyPkg == null) {
                            proxyPkg = pkg;
                        } else if (!pkg.equals(proxyPkg)) {
                            throw new IllegalArgumentException(
                                    "non-public interfaces from different packages");
                        }
                    }
                }
                //如果未传入接口或者未找到包名,则使用默认包名com.sun.proxy.
                if (proxyPkg == null) {
                    // if no non-public proxy interfaces, use com.sun.proxy package
                    proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
                }
        
                {
                    //生成一个代理类的名称,规则是 包名+jdk代理类前缀$Proxy+计数
                    long num;
                    synchronized (nextUniqueNumberLock) {
                        num = nextUniqueNumber++;
                    }
                    String proxyName = proxyPkg + proxyClassNamePrefix + num;
                    /**
                     * 校验是否已经加载了代理类,这一步好像是没有逻辑
                     * Verify that the class loader hasn't already
                     * defined a class with the chosen name.
                     */
        
                    //生成一个代理类
                    byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                            proxyName, interfaces);
                    try {
                        proxyClass = defineClass0(loader, proxyName,
                                proxyClassFile, 0, proxyClassFile.length);
                    } catch (ClassFormatError e) {
                        /*
                         * A ClassFormatError here means that (barring bugs in the
                         * proxy class generation code) there was some other
                         * invalid aspect of the arguments supplied to the proxy
                         * class creation (such as virtual machine limitations
                         * exceeded).
                         */
                        throw new IllegalArgumentException(e.toString());
                    }
                }
                //将代理类添加到proxyClasses Map中,用于isProxyClass方法中使用,判断类是否为代理类
                // add to set of all generated proxy classes, for isProxyClass
                proxyClasses.put(proxyClass, null);
        
            } finally {
                /**
                 * 我们必须以某种方式清除代理类缓存项的“挂起的生成”状态。
                 * 如果成功生成了代理类,则将其存储在缓存中(使用弱引用);否则,请删除保留项。
                 * 在所有情况下,都要通知此缓存中保留项的所有等待队列中的线程。
                 */
                synchronized (cache) {
                    if (proxyClass != null) {
                        //代理类创建成功
                        //根据接口数组 作为key,将代理类封装成一个索引用放入缓存map中
                        cache.put(key, new WeakReference(proxyClass));
                    } else {
                        //代理类创建失败,则在缓存中删除key
                        cache.remove(key);
                    }
                    //唤醒其他等待的线程,
                    cache.notifyAll();
                }
            }
            return proxyClass;
        }
        

分享:

低价透明

统一报价,无隐形消费

金牌服务

一对一专属顾问7*24小时金牌服务

信息保密

个人信息安全有保障

售后无忧

服务出问题客服经理全程跟进