JDK动态代理源码剖析
关键代码:
1.Proxy.newInstance:
private static final Class<?>[] constructorParams = { InvocationHandler.class };
Class<?> cl = getProxyClass0(loader, intfs);
final Constructor<?> cons = cl.getConstructor(constructorParams);
return cons.newInstance(new Object[]{h});
2.Proxy.getProxyClass0:
// otherwise, it will create the proxy class via the ProxyClassFactory
return proxyClassCache.get(loader, interfaces);
3.WeakCache.get(由2注释可知,首次是由ProxyClassFactory生成的class对象,proxyClassCache即WeakCache):
Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
可见,这里调用ProxyClassFactory的apply方法;
4.ProxyClassFactory.apply:
long num = nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg + proxyClassNamePrefix + num;
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags);
return defineClass0(loader, proxyName,proxyClassFile, 0, proxyClassFile.length);
这里先取一个原子整数作为序号,生成代理对象名称,com.sun.proxy.$Proxy0.class,
然后通过ProxyGenerator.generateProxyClass获得class的字节码,然后调用native方法defineClass0创建class对象。
由上可知,先在ProxyClassFactory的apply方法中通过ProxyGenerator.generateProxyClass得到字节码,调用defineClass0由字节码得到class对象(是个native方法),然后在Proxy.newInstance里得到这个class对象的构造器,然后反射得到代理对象实例。
通过ProxyGenerator.generateProxyClass(Openjdk能看到该类的源码)可以生成代理对象的字节码byte[] data,然后将其写到磁盘文件(.class后缀),即可看到代理对象的class文件了:
FileOutputStream fos = new FileOutPutStream("$Proxy0.class");
fos.write(data);
fos.close();
使用jd反编译:
该class继承了Proxy,实现了被代理对象的接口。构造方法传入InvocationHandler,调用super(invocationHandler);实现的被代理接口的方法里面其实是调用的invocationHandler.invoke方法(Object proxy参数传入的代理对象this)。
使用动态代理:
1)实现InvocationHandler接口(增强),并持有被代理对象实例,并在它的invoke方法里面写增强逻辑,该方法的参数是代理对象,方法和参数,在invoke合适的位置调用被代理对象的方法(使用反射的方式method.invoke(target, args));
2)使用Proxy.newInstance创建代理对象,classloader(加载生成的动态代理类字节码为class对象)使用被代理对象的classloader即可(target.getClass.getClassLoader),interfaces使用被代理对象的接口数组(target.getClass.getInterfaces)。
return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length);
JDK动态代理源码剖析的更多相关文章
- 深入剖析JDK动态代理源码实现
动态代理.静态代理优缺点优点:业务类只需要关注业务逻辑本身,保证了业务类的重用性.这是代理的共有优点.动态代理只有在用到被代理对象的时候才会对被代理类进行类加载. 而静态代理在编译器就已经开始占内存了 ...
- JDK动态代理源码学习
继上一篇博客设计模式之代理模式学习之后http://blog.csdn.net/u014427391/article/details/75115928,本博客介绍JDK动态代理的实现原理,学习一下JD ...
- jdk 动态代理源码分析
闲来无事,撸撸源码 使用方法 直接看代码吧.. package com.test.demo.proxy; import java.lang.reflect.InvocationHandler; imp ...
- JDK动态代理源码解析
动态代理.静态代理优缺点 关于JDK的动态代理,最为人熟知的可能要数Spring AOP的实现,默认情况下,Spring AOP的实现对于接口来说就是使用的JDK的动态代理来实现的,而对于类的 ...
- JDK动态代理源码分析
先抛出一个问题,JDK的动态代理为什么不支持对实现类的代理,只支持接口的代理??? 首先来看一下如何使用JDK动态代理.JDK提供了Java.lang.reflect.Proxy类来实现动态代理的,可 ...
- 设计模式之JDK动态代理源码分析
这里查看JDK1.8.0_65的源码,通过debug学习JDK动态代理的实现原理 大概流程 1.为接口创建代理类的字节码文件 2.使用ClassLoader将字节码文件加载到JVM 3.创建代理类实例 ...
- 动态代理学习(二)JDK动态代理源码分析
上篇文章我们学习了如何自己实现一个动态代理,这篇文章我们从源码角度来分析下JDK的动态代理 先看一个Demo: public class MyInvocationHandler implements ...
- java 1.8 动态代理源码分析
JDK8动态代理源码分析 动态代理的基本使用就不详细介绍了: 例子: class proxyed implements pro{ @Override public void text() { Syst ...
- java动态代理源码解析
众所周知,java动态代理同反射原理一直是许多框架的底层实现,之前一直没有时间来分析动态代理的底层源码,现结合源码分析一下动态代理的底层实现 类和接口 java动态代理的主要类和接口有:java.la ...
随机推荐
- Redis 系列
Redis 系列 [Redis 系列(01)安装配制] [Redis 系列(02)数据结构] [Redis 系列(03-1)进阶 - 发布订阅] [Redis 系列(03-2)进阶 - 事务] [Re ...
- SpringCloud 使用Feign访问服务
Feign简介: 声明式的Rest WEB 服务的客户端, https://github.com/OpenFeign/feign.Spring Cloud 提供了Spring-cloud-start ...
- Oracle学习笔记<3>
单值函数 1.函数的分类 Oracle数据库中函数分为两类: 1)单值函数 n条数据经过函数处理得到n条结果 例如:查询所有员工last_name,并以全部大写形式输出 2)多值函数(组函数) n条数 ...
- Java使用Jsoup简单解析页面
jsoup 是一款 Java 的 HTML 解析器,可直接解析某个 URL 地址.HTML 文本内容.它提供了一套非常省力的 API,可通过 DOM,CSS 以及类似于 jQuery 的操作方法来取出 ...
- 从FreeBSD里面看到的网络协议列表,感觉可以保存一下
# # Internet protocols # # $FreeBSD$ # from: @(#)protocols 5.1 (Berkeley) 4/17/89 # # See also http: ...
- Provider
import React from 'react';import PropTypes from 'prop-types'; class Provider extends React.Component ...
- windows server 2012 R2修改默认远程端口
因客户现场网络复杂,将windows系统的默认远程端口3389归入安全策略中,所以服务器需要修改此端口,配置如下: 首先:登录操作系统,win+R调出运行菜单后输入regedit, 进入注册表编辑相关 ...
- Intellij idea创建javaWeb:实现JSP/Servlet(转)
转自:https://www.jianshu.com/p/9684e90cf7b5 Intellij idea创建javaWeb:实现JSP/Servlet by_love唯念 关注 2016.12. ...
- day12 python函数名的应用 闭包 迭代器
day12 python 一.函数名的应用(是第一类对象) 函数名的命名规范和变量是一样的 函数名其实就是变量名 def func(): print('i am funct ...
- 深度探索C++对象模型第四章:函数语义学
C++有三种类型的成员函数:static/nonstatic/virtual 一.成员的各种调用方式 C with class 只支持非静态成员函数(Nonstatic member function ...