入口是java.lang.reflect.Proxy#newProxyInstance

简化一下就三步:


//从缓存查找代理类,或者生成指定的代理类
Class<?> cl = getProxyClass0(loader, intfs);
//获取public构造器,如果不是public 设置为可访问
final Constructor<?> cons = cl.getConstructor(constructorParams)
//调用有参构造器创建实例
cons.newInstance(new Object[]{h})

再来看看java.lang.reflect.Proxy#getProxyClass0()这个方法,注释的意思是,如果当前classLoader已经创建了代理类,就copy一份,如果没有就创建一个。里面实际是调用了

proxyClassCache.get(loader, interfaces)

我们再来看WeakCache.get(loader, interfaces)这个方法。

      //1.包装key为CacheKey    Object cacheKey = CacheKey.valueOf(key, refQueue);      // lazily install the 2nd level valuesMap for the particular cacheKeyConcurrentMap<Object, Supplier<V>> valuesMap = map.get(cacheKey);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//2.通过SubKeyFactory创建key对象Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));Supplier<V> supplier = valuesMap.get(subKey);Factory factory = null;while (true) {if (supplier != null) {// supplier might be a Factory or a CacheValue<V> instance//4.实际调用了内部类Factory的get()方法,创建了一个代理类V value = supplier.get();if (value != null) {return value;}}//.........省略了一部分// lazily construct a Factory//3.实例化内部类Factoryif (factory == null) {factory = new Factory(key, parameter, subKey, valuesMap);}//..........省略...........}

这个内部类java.lang.reflect.WeakCache.Factory#get的源码如下

            // create new value//1.关键代码:创建Value即代理类V value = null;try {value = Objects.requireNonNull(valueFactory.apply(key, parameter));} finally {if (value == null) { // remove us on failurevaluesMap.remove(subKey, this);}}// the only path to reach here is with non-null valueassert value != null;// wrap value with CacheValue (WeakReference)// 2.包装value成CacheValueCacheValue<V> cacheValue = new CacheValue<>(value);//3. 放到reverseMap,以及替换掉旧的valuesMap中的valuereverseMap.put(cacheValue, Boolean.TRUE);

第二步valueFactory.apply(key, parameter)很重要。

在Proxy中有个方法分别创建了KeyFactory(这个就是keyFactory对象)和ProxyClassFactory(这个就是valueFactory对象)

/*** a cache of proxy classes*/private static final WeakCache<ClassLoader, Class<?>[], Class<?>>proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());

那我们就来看Proxy的内部类ProxyClassFactory.apply(key, parameter)这个方法。

            //上面代码略过,是选择包名,以接口包作为包名            /** Choose a name for the proxy class to generate.*///1.给代理类命名。包名+类名+自增数long num = nextUniqueNumber.getAndIncrement();String proxyName = proxyPkg + proxyClassNamePrefix + num;/** Generate the specified proxy class.*///2.生成特定的代理类字节码byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags);try {//3.将字节码转换为对象return defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length);} catch (ClassFormatError e) {}

这三部走完就算是完成创建代理类的细节了。

JDK动态代理源码解读相关推荐

  1. jdk动态代理源码分析(一)---代理的定义

    最近在看rpc的实现原理,发现大部分通用的rpc框架在实现远程调用的时候,都是通过java动态代理封装好了通信细节,让用户可以像调用本地服务一样调用远程服务.但是关于java动态代理有两个问题想不通: ...

  2. JDK动态代理源码解析

    分析版本jdk1.8 在分析jdk动态代理之前,先来了解java WeakReference弱引用的使用.运行期创建目标对象的代理非常耗时,使用缓存来存储生成的代理类显得尤为重要.jdk动态代理使用弱 ...

  3. 深入剖析JDK动态代理源码实现

    动态代理.静态代理优缺点 优点:业务类只需要关注业务逻辑本身,保证了业务类的重用性.这是代理的共有优点.动态代理只有在用到被代理对象的时候才会对被代理类进行类加载. 而静态代理在编译器就已经开始占内存 ...

  4. 动态代理及JDK动态代理源码分析

    1.为什么要动态代理 现在有这样一个需求:在聊天系统中,把每一个所说的话记录到日志文件里面,初学者可能是这样来设计 在speak方法中调用log方法,记录到数据库.这样设计有明显的不足:1.log方法 ...

  5. jdk动态代理源码学习

    最近用到了java的动态代理,虽然会用,但不了解他具体是怎么实现,抽空看看了看他的源码. 说到Java的动态代理就不能不说到代理模式,动态代理也就是多了一个'动态'两字,在<大话设计模式> ...

  6. Java动态代理源码详解

    一.概述   前言:本文除了讲解JDK动态代理及CGLIB动态代理实例和应用外,还会讲解JDK动态代理源码实现过程以及自己写一手个JDK动态代理等.   动态代理在很多底层框架中都会用得到,比如在Sp ...

  7. javabean反射改字段内容_BAT程序员编写:深入理解 Java 反射和动态代理源码分析...

    什么是反射 反射(Reflection)是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性. 通过反射机制,可以在运行时访问 Java ...

  8. 动态代理源码分析,实现自己的动态代理

    什么是代理 增强一个对象的功能 买火车票,app就是一个代理,他代理了火车站,小区当中的代售窗口 java当中如何实现代理 java实现的代理的两种办法 代理的名词 代理对象 增强后的对象 目标对象 ...

  9. Android动态代理源码分析

    前言 前面我们简单介绍了代理模式的使用Android设计模式详解之代理模式,我们也明白了动态代理模式的重要性,那动态代理究竟是如何实现将方法交给InvocationHandler.invoke执行的呢 ...

  10. jkd动态代理源码分析

    代理对象的生成方法是: Proxy.newProxyInstance(...),进入这个方法内部,一步一步往下走会发现会调用 ProxyGenerator.generateProxyClass(),这 ...

最新文章

  1. 【解决方法】你已从聊天服务器断开,正在尝试重新连接
  2. C#线程学习的一点体会和总结
  3. 2008秋-计算机软件基础- 实验一 参考源程序
  4. 全国各地区最低工资标准情况(截至2020年3月31日)
  5. jvm性能调优 - 06线上应用部署JVM实战_堆内存预估与设置
  6. css多行文本溢出显示省略号(兼容ie)
  7. Zabbix监控配置
  8. Mac OS git多次需要输入用户名密码config解决
  9. 电子产品可靠性测试报告
  10. 达梦数据库基础优化分享
  11. 功耗:Leakage Power
  12. c软件查表获得电量代码_energy.c 源代码在线查看 - 基于单片机的多费率电能表源程序 资源下载 虫虫电子下载站...
  13. 那群“沙雕”年轻人,正在闲鱼上蹦迪
  14. CAD高版本窗体阵列LISP_AutoCAD高版本把阵列对话框调出来
  15. 37岁的老大叔零基础学python,来点鼓励吧
  16. 测试时间不够,项目要如期发布如何保证测试质量
  17. 史上最牛老丈人,三个朝代全是自家人
  18. SQL注入的攻击与防御(简单篇)
  19. 如何最用最懒的方式获取百度地图的行政区边界坐标范围
  20. DEV gridcontrol 汉化类

热门文章

  1. 迈信EP100伺服驱动器方案
  2. android fastboot流程,FastBoot的使用步骤
  3. TR069协议与商业应用8——移植cwmp到ARM平台运行和测试
  4. 三星手机性能测试软件,三星Galaxy S III性能速测:一个字“快”
  5. 4.4 数值分析: 局部收敛性
  6. 软件测试报告模板--实用--绝对靠谱
  7. 暗月渗透实战靶场-项目八(上)
  8. html全部布局代码大全,HTML 布局(示例代码)
  9. 解决 最新版 mac 系统 无法使用未签名第三驱动(绿联usb网卡不正常)
  10. MySQL数据恢复--binlog