关键代码:

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);

最新文章

  1. Android Studio中的CmakeList NDK配置
  2. Android屏幕适配
  3. &lt;&lt;Exceptional C++&gt;&gt; notes
  4. JavaWeb 学习009-4个页面,5条sql语句(添加、查看、修改、删除)
  5. 运行时---关联Associated
  6. andorid 文字颜色selector的使用
  7. asp.net中webservice与android的json数据交互方式设置
  8. Andriod:如何卸载模拟器上已经安装的应用程序?
  9. QML基础(六篇文章)
  10. 嵌套json的查询
  11. 【Java核心】ClassLoader原理及其使用
  12. 《UNP》学习之TCP状态转换
  13. php获取脚本执行的参数
  14. JAVA的三个版本EE,SE,ME
  15. jQuery ajax读取本地json文件
  16. LEAPMOTION开发UI专题(1)
  17. IOC容器特性注入第三篇:Attribute封装
  18. 在浏览器中直接调用webservice的正确写法
  19. preset
  20. flask的orm操作

热门文章

  1. java File I/O
  2. 使用vue配合组件--转载
  3. C#用new和override来实现抽象类的重写区别
  4. k8s之ingress-nginx部署一直提示健康检查10254端口不通过问题就处理
  5. C常量与变量
  6. elk 解决浏览器跨域问题
  7. 【知识强化】第四章 网络层 4.3 IP
  8. Failed to resolve com.android.support:support-compat:25.4.0
  9. WebDriverAgent安装
  10. shell 根据路径获取文件名和目录