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);
原文地址:https://www.cnblogs.com/kibana/p/10176847.html