JDK动态代理源码解读
入口是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动态代理源码解读相关推荐
- jdk动态代理源码分析(一)---代理的定义
最近在看rpc的实现原理,发现大部分通用的rpc框架在实现远程调用的时候,都是通过java动态代理封装好了通信细节,让用户可以像调用本地服务一样调用远程服务.但是关于java动态代理有两个问题想不通: ...
- JDK动态代理源码解析
分析版本jdk1.8 在分析jdk动态代理之前,先来了解java WeakReference弱引用的使用.运行期创建目标对象的代理非常耗时,使用缓存来存储生成的代理类显得尤为重要.jdk动态代理使用弱 ...
- 深入剖析JDK动态代理源码实现
动态代理.静态代理优缺点 优点:业务类只需要关注业务逻辑本身,保证了业务类的重用性.这是代理的共有优点.动态代理只有在用到被代理对象的时候才会对被代理类进行类加载. 而静态代理在编译器就已经开始占内存 ...
- 动态代理及JDK动态代理源码分析
1.为什么要动态代理 现在有这样一个需求:在聊天系统中,把每一个所说的话记录到日志文件里面,初学者可能是这样来设计 在speak方法中调用log方法,记录到数据库.这样设计有明显的不足:1.log方法 ...
- jdk动态代理源码学习
最近用到了java的动态代理,虽然会用,但不了解他具体是怎么实现,抽空看看了看他的源码. 说到Java的动态代理就不能不说到代理模式,动态代理也就是多了一个'动态'两字,在<大话设计模式> ...
- Java动态代理源码详解
一.概述 前言:本文除了讲解JDK动态代理及CGLIB动态代理实例和应用外,还会讲解JDK动态代理源码实现过程以及自己写一手个JDK动态代理等. 动态代理在很多底层框架中都会用得到,比如在Sp ...
- javabean反射改字段内容_BAT程序员编写:深入理解 Java 反射和动态代理源码分析...
什么是反射 反射(Reflection)是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序获取自身的信息,并且可以操作类或对象的内部属性. 通过反射机制,可以在运行时访问 Java ...
- 动态代理源码分析,实现自己的动态代理
什么是代理 增强一个对象的功能 买火车票,app就是一个代理,他代理了火车站,小区当中的代售窗口 java当中如何实现代理 java实现的代理的两种办法 代理的名词 代理对象 增强后的对象 目标对象 ...
- Android动态代理源码分析
前言 前面我们简单介绍了代理模式的使用Android设计模式详解之代理模式,我们也明白了动态代理模式的重要性,那动态代理究竟是如何实现将方法交给InvocationHandler.invoke执行的呢 ...
- jkd动态代理源码分析
代理对象的生成方法是: Proxy.newProxyInstance(...),进入这个方法内部,一步一步往下走会发现会调用 ProxyGenerator.generateProxyClass(),这 ...
最新文章
- 【解决方法】你已从聊天服务器断开,正在尝试重新连接
- C#线程学习的一点体会和总结
- 2008秋-计算机软件基础- 实验一 参考源程序
- 全国各地区最低工资标准情况(截至2020年3月31日)
- jvm性能调优 - 06线上应用部署JVM实战_堆内存预估与设置
- css多行文本溢出显示省略号(兼容ie)
- Zabbix监控配置
- Mac OS git多次需要输入用户名密码config解决
- 电子产品可靠性测试报告
- 达梦数据库基础优化分享
- 功耗:Leakage Power
- c软件查表获得电量代码_energy.c 源代码在线查看 - 基于单片机的多费率电能表源程序 资源下载 虫虫电子下载站...
- 那群“沙雕”年轻人,正在闲鱼上蹦迪
- CAD高版本窗体阵列LISP_AutoCAD高版本把阵列对话框调出来
- 37岁的老大叔零基础学python,来点鼓励吧
- 测试时间不够,项目要如期发布如何保证测试质量
- 史上最牛老丈人,三个朝代全是自家人
- SQL注入的攻击与防御(简单篇)
- 如何最用最懒的方式获取百度地图的行政区边界坐标范围
- DEV gridcontrol 汉化类
热门文章
- 迈信EP100伺服驱动器方案
- android fastboot流程,FastBoot的使用步骤
- TR069协议与商业应用8——移植cwmp到ARM平台运行和测试
- 三星手机性能测试软件,三星Galaxy S III性能速测:一个字“快”
- 4.4 数值分析: 局部收敛性
- 软件测试报告模板--实用--绝对靠谱
- 暗月渗透实战靶场-项目八(上)
- html全部布局代码大全,HTML 布局(示例代码)
- 解决 最新版 mac 系统 无法使用未签名第三驱动(绿联usb网卡不正常)
- MySQL数据恢复--binlog