jdk动态代理: 从源码,到字节码,到自己手写动态代理

注意

本篇文章,讲解非常详细.已经到了字节码层面.内容和篇幅较多.请有耐心,并按照源码依依查看.  

文末有福利!

 反编译查看: 动态代理生成的字节码

  • 分析: 所有的方法处理,都转发给InvocationHandler

源码分析: Proxy.newProxyInstance()

  • 作用: 安全校验,Class反射构造器创建对象

  1.  获取所有接口

  2.  获取动态对象的Class

  3.  反射获取构造器

  4.  通过构造器,创建对象

  • 核心: Class cl = getProxyClass0(loader,infs)

    public static Object newProxyInstance(ClassLoader loader,                                          Class<?>[] interfaces,                                          InvocationHandler h)        throws IllegalArgumentException{
          // lzy分析: null判断        Objects.requireNonNull(h);        // lzy分析: 获取所有需要动态代理的接口        final Class<?>[] intfs = interfaces.clone();        // lzy分析:  系统安全校验器        final SecurityManager sm = System.getSecurityManager();        if (sm != null) {
              // lzy分析: 安全校验            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);        }
        /*         * Look up or generate the designated proxy class.         */        // lzy分析(核心): 生成代理类的Class对象        Class<?> cl = getProxyClass0(loader, intfs);
        /*         * Invoke its constructor with the designated invocation handler.         */        try {
              if (sm != null) {
                  // lzy分析: 安全校验                checkNewProxyPermission(Reflection.getCallerClass(), cl);            }            // lzy分析: 反射获取构造器            final Constructor<?> cons = cl.getConstructor(constructorParams);            final InvocationHandler ih = h;            // lzy分析: 判断构造方法权限修饰符.如果没有权限,强制访问.            if (!Modifier.isPublic(cl.getModifiers())) {
                  AccessController.doPrivileged(new PrivilegedAction<Void>() {
                      public Void run() {
                          cons.setAccessible(true);                        return null;                    }                });            }            // lzy分析: 通过构造方法创建对象.            // h是InvocationHandler,代理对象的处理器.            return cons.newInstance(new Object[]{h});        } catch (IllegalAccessException|InstantiationException e) {
              throw new InternalError(e.toString(), e);        } catch (InvocationTargetException e) {
              Throwable t = e.getCause();            if (t instanceof RuntimeException) {
                  throw (RuntimeException) t;            } else {
                  throw new InternalError(t.toString(), t);            }        } catch (NoSuchMethodException e) {
              throw new InternalError(e.toString(), e);        }    }

源码分析: Proxy.getProxyClass0(loader,infs)​​​​​​

        // lzy分析: 接口个数限制        if (interfaces.length > 65535) {
              throw new IllegalArgumentException("interface limit exceeded");        }
        // If the proxy class defined by the given loader implementing        // the given interfaces exists, this will simply return the cached copy;        // otherwise, it will create the proxy class via the ProxyClassFactory        // lzy分析: 通过类加载器loader 和 所有代理接口interfaces,从缓存中获取        return proxyClassCache.get(loader, interfaces);

源码分析: WeakCache.get()

  •  作用: 获取工厂,利用工厂创建代理对象

  1.  类加载获取,已经加载的接口

  2.  所有接口进行Hash唯一标识

  3.  准备创建工厂

  4.  通过工厂创建代理对象

  5.   重试机制: 工厂存在问题,循环中将创建新工厂

  •  核心: V value = suppile.get()

    public V get(K key, P parameter) {
          // lzy分析: null指针判断        Objects.requireNonNull(parameter);        // lzy分析: 将进入ReferenceQueue队列中数据,删除掉        expungeStaleEntries();        // lzy分析: 类加载器 和 引用队列,存储到WeakReference引用中        Object cacheKey = CacheKey.valueOf(key, refQueue);
        // lazily install the 2nd level valuesMap for the particular cacheKey        // lzy分析: 通过类加载器,获取已加载过的接口和接口工厂        // key: 类加载器的WeakReference封装        // value:         //     key: 接口元数据        //     value: 接口工厂(作用: 创建动态代理对象)        ConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);        // lzy分析: 初始化操作,如果是第一次.那么创建一个空的Map        if (valuesMap == null) {
              ConcurrentMap<Object, Supplier<V>> oldValuesMap                = map.putIfAbsent(cacheKey,                                  valuesMap = new ConcurrentHashMap<>());            if (oldValuesMap != null) {
                  valuesMap = oldValuesMap;            }        }
        // create subKey and retrieve the possible Supplier<V> stored by that        // subKey from valuesMap        // lzy分析: 将所有接口进行hash唯一标识. 确保对应着一个工厂.        Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));        // lzy分析: 通过接口元数据对象,尝试性获取工厂        Supplier<V> supplier = valuesMap.get(subKey);        Factory factory = null;
        while (true) {
              // lzy分析: 第一次是没有工厂的.             // 这一步在第一次会跳过 , 下面代码将创建工厂            // 通常情况下,执行这一步.是在第二次循环.            // 因为第一次循环,是在创建工厂            // 只有到了第二次循环,工厂才被创建好.            if (supplier != null) {
                  // supplier might be a Factory or a CacheValue<V> instance                // 利用工厂进行创建                V value = supplier.get();                if (value != null) {
                      return value;                }            }            // else no supplier in cache            // or a supplier that returned null (could be a cleared CacheValue            // or a Factory that wasn't successful in installing the CacheValue)
            // lazily construct a Factory            // 创建一个工厂            if (factory == null) {
                  factory = new Factory(key, parameter, subKey, valuesMap);            }



            if (supplier == null) {
                  // 将工厂放入缓存中                supplier = valuesMap.putIfAbsent(subKey, factory);                if (supplier == null) {
                      // successfully installed Factory                    // 已经创建好了,为第二次循环作准备.                    // 第二次循环,可以利用工厂进行创建                    supplier = factory;                }                // else retry with winning supplier                // lzy分析: 这是工厂的重试机制                // 触发条件: V value = supplier.get();                // 通过工厂创建对象,是null值            } else {
                  // lzy分析: 由于旧工厂存在问题,无法成功创建对                // 那么使用新工厂来代替旧工厂.                // 意味着: 将进入下一轮循环.用新工厂,创建对象.                if (valuesMap.replace(subKey, supplier, factory)) {
                      // successfully replaced                    // cleared CacheEntry / unsuccessful Factory                    // with our Factory                    supplier = factory;                } else {
                      // retry with current supplier                    supplier = valuesMap.get(subKey);                }            }        }    }

源码细节分析: CacheKey.valueOf(key,refQueue)

  • 作用:弱引用,GC触发时一定会被回收.但WeakReference对象本身,将进入到ReferenceQueue中

    private static final class CacheKey<K> extends WeakReference<K> {
              static <K> Object valueOf(K key, ReferenceQueue<K> refQueue) {
              return key == null                   // null key means we can't weakly reference it,                   // so we use a NULL_KEY singleton as cache key                   ? NULL_KEY                   // non-null key requires wrapping with a WeakReference                   : new CacheKey<>(key, refQueue);        }    }

源码细节分析: WeakCache.expungeStaleEntries()

  •  作用: 每次创建动态代理时,都会先清理一遍因GC触发而保留下来的Reference中引用.

    private void expungeStaleEntries() {
          CacheKey<K> cacheKey;        while ((cacheKey = (CacheKey<K>)refQueue.poll()) != null) {
              cacheKey.expungeFrom(map, reverseMap);        }    }

源码细节分析: Proxy.KeyFactory.apply()

  • 作用:  将所有接口进行hash值.确保唯一标识,对应着一个工厂

  • 位置:   subkeyFactory.apply(key,parameter)

    private static final class KeyFactory        implements BiFunction<ClassLoader, Class<?>[], Object>{
          @Override        public Object apply(ClassLoader classLoader, Class<?>[] interfaces) {
              switch (interfaces.length) {
                  case 1: return new Key1(interfaces[0]); // the most frequent                case 2: 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值