回顾:
上一篇代理之JDK动态代理我们了解来JDK动态代理的使用。同样也遗留了两个问题:1、代理对象是怎么生成的?2、InvocationHandler的invoke方法是由谁来调用的?
jdk动态代理源码:
首先来看一下JDK是怎样生成代理对象的。既然生成代理对象是用的Proxy类的静态方newProxyInstance,那么我们就去它的源码里看一下它到底都做了些什么?
Java1.8 源码(以下代码代码不全,只截取关键性代码):
/**
* loader:类加载器
* interfaces:目标对象实现的接口
* h:InvocationHandler的实现类
*/
public static Object newProxyInstance(ClassLoader loader,Class[] interfaces,
InvocationHandler h)throws IllegalArgumentException{
//判断h不能为null。为null 抛出:NullPointerException
Objects.requireNonNull(h);
final Class[] intfs = interfaces.clone();
//查找或生成指定的代理类
Class cl =getProxyClass0(loader, intfs);
try {
//获取构造方法
final Constructor cons = cl.getConstructor();
final InvocationHandler ih = h;
//如果构造方法不是public 设置构造方法为可访问
if (!Modifier.isPublic(cl.getModifiers())) {
AccessController.doPrivileged(new PrivilegedAction() {
public Void run() {
cons.setAccessible(true);
return null;
}
});
}
/ /放射创建对象
return cons.newInstance(new Object[]{h});
}catch (Exception e) {
throw new InternalError(e.toString(), e);
}
}
以上代码可以看出:通过newProxyInstance方法是getProxyClass0获取Class对象,后通过反射创建对象。那getProxyClass0就看看getProxyClass0是什么获取Class对象的:
private static ClassgetProxyClass0(ClassLoader loader, Class... interfaces) {
//这里限制了目标对象实现的接口的个数
if (interfaces.length >65535) {
throw new IllegalArgumentException("interface limit exceeded");
}
return proxyClassCache.get(loader, interfaces);
}
/*
*如果缓存中有,就直接返回,否则会生成
*key:类加载器;parameter:接口数组
*/
public V get(K key, P parameter) {
//省略部分缓存机制代码
...
Factory factory =null;
//下面用到了 CAS+重试 实现的多线程安全的 非阻塞算法
while (true) {
//最终执行的代码 从supplier.get()中获取返回值
if (supplier !=null) {
V value = supplier.get();
if (value !=null) {
return value;
}
}
if (factory ==null) {
factory =new Factory(key, parameter, subKey, valuesMap);
}
if (supplier ==null) {
supplier = valuesMap.putIfAbsent(subKey, factory);
if (supplier ==null) {
supplier = factory;
}
}else {
if (valuesMap.replace(subKey, supplier, factory)) {
supplier = factory;
}else {
supplier = valuesMap.get(subKey);
}
}
}
}
以上代码重点是: V value = supplier.get() 获取最终的返回的class对象
public synchronized V get() {
Supplier supplier =valuesMap.get(subKey);
if (supplier !=this) {
return null;
}
V value =null;
try {
//这里是创建返回Class对象(valueFactory.apply(key, parameter))
value = Objects.requireNonNull(valueFactory.apply(key, parameter));
}finally {
if (value ==null) {
valuesMap.remove(subKey, this);
}
}
assert value !=null;
CacheValue cacheValue =new CacheValue<>(value);
reverseMap.put(cacheValue, Boolean.TRUE);
if (!valuesMap.replace(subKey, this, cacheValue)) {
throw new AssertionError("Should not reach here");
}
return value;
}
}
我们继续关注:valueFactory.apply方法看看是什么创建Class对象的:
public Classapply(ClassLoader loader, Class[] interfaces) {
Map, Boolean> interfaceSet =new IdentityHashMap<>(interfaces.length);
for (Class intf : interfaces) {
Class interfaceClass =null;
try {
// 加载目标类实现的接口到内存中
interfaceClass = Class.forName(intf.getName(), false, );
}catch (ClassNotFoundException e) {
}
if (interfaceClass != intf) {
throw new IllegalArgumentException(intf +" is not visible from class loader");
}
//如果不是接口 就抛IllegalArgumentException
if (!interfaceClass.isInterface()) {
throw new IllegalArgumentException(
interfaceClass.getName() +" is not an interface");
}
if (interfaceSet.put(interfaceClass, Boolean.TRUE) !=null) {
throw new IllegalArgumentException(
"repeated interface: " + interfaceClass.getName());
}
}
String proxyPkg =null;
int accessFlags = Modifier.PUBLIC | Modifier.FINAL;
// 验证所有非公共代理接口都在同一个包中。如果不是者抛异常
for (Class intf : interfaces) {
int flags = intf.getModifiers();
if (!Modifier.isPublic(flags)) {
accessFlags = Modifier.FINAL;
String name = intf.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");
}
}
}
if (proxyPkg ==null) {
proxyPkg = ReflectUtil.PROXY_PACKAGE +".";
}
long num =nextUniqueNumber.getAndIncrement();
String proxyName = proxyPkg +proxyClassNamePrefix + num;
//这个是重点:生成类字节码的方法
byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
proxyName, interfaces, accessFlags);
try {
// 根据代理类的字节码生成代理类的实例
return defineClass0(loader, proxyName, proxyClassFile, 0,
proxyClassFile.length);
}catch (ClassFormatError e) {
throw new IllegalArgumentException(e.toString());
}
}
}
我们继续跟踪ProxyGenerator.generateProxyClass方法:
public static byte[] generateProxyClass(final String var0, Class[] var1, int var2) {
ProxyGenerator var3 =new ProxyGenerator(var0, var1, var2);
//真正生成字节码的方法
final byte[] var4 = var3.generateClassFile();
//如果saveGeneratedFiles为true 则生成字节码文件,所以在开始我们要设置这个参数
if (saveGeneratedFiles) {
AccessController.doPrivileged(new PrivilegedAction() {
public Void run() {
try {
int var1 = var0.lastIndexOf(46);
Path var2;
if (var1 >0) {
Path var3 = Paths.get(var0.substring(0, var1).replace('.', File.separatorChar));
Files.createDirectories(var3);
var2 = var3.resolve(var0.substring(var1 +1, var0.length()) +".class");
}else {
var2 = Paths.get(var0 +".class");
}
Files.write(var2, var4, new OpenOption[0]);
return null;
}catch (IOException var4x) {
throw new InternalError("I/O exception saving generated file: " + var4x);
}
}
});
}
return var4;
}
var3.generateClassFile为正真创建字节码的方法,涉及字节码文件的语法,在此我们就不在深入的探究。
总结:代理对象是的创建过程一共分三个步骤:
1、ProxyGenerator.generateProxyClass方法负责生成代理类的字节码,生成逻辑比较复 杂,了解原理继续分析源码 sun.misc.ProxyGenerator;
2、native方法Proxy.defineClass0负责字节码加载的实现,并返回对应的Class对象。
3、利用clazz.newInstance反射机制生成代理类的对象;
至此我们明白了代理对象是怎么生成的,那么InvocationHandler的invoke方法是由谁来调用的???
“知其然,知其所以然”
网友评论