加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

JDK动态代理实现原理--转载

发布时间:2020-12-14 06:19:44 所属栏目:Java 来源:网络整理
导读:之前虽然会用JDK的动态代理,但是有些问题却一直没有搞明白。比如说:InvocationHandler的invoke方法是由谁来调用的,代理对象是怎么生成的,直到前几个星期才把这些问题全部搞明白了。???? 废话不多说了,先来看一下JDK的动态是怎么用的。? ?? ?? ?????? ??

之前虽然会用JDK的动态代理,但是有些问题却一直没有搞明白。比如说:InvocationHandler的invoke方法是由谁来调用的,代理对象是怎么生成的,直到前几个星期才把这些问题全部搞明白了。???? 废话不多说了,先来看一下JDK的动态是怎么用的。?

  1. ??
  2. ??
  3. ??????
  4. ????
  5. ????
  6. ??????
  7. ????
  8. ????
  9. ????????
  10. ????????
  11. ????}??
  12. ??
  13. ??
  14. ????
  15. ????
  16. ??????????
  17. ????????
  18. ????????System.out.println(
  19. ??????????
  20. ????????
  21. ????????Object?result?=?method.invoke(target,?args);??
  22. ??????????
  23. ????????
  24. ????????System.out.println(
  25. ??????????
  26. ????????
  27. ????}??
  28. ??
  29. ????
  30. ????
  31. ????????
  32. ????????????????target.getClass().getInterfaces(),?
  33. ????}??
  34. }??
  35. ??
  36. ??
  37. ??
  38. ????
  39. ????
  40. ??
  41. }??
  42. ??
  43. ??
  44. ??
  45. ????
  46. ????
  47. ????????System.out.println(
  48. ????}??
  49. }??
  50. ??
  51. ??
  52. ??
  53. ??
  54. ????
  55. ????
  56. ????????
  57. ????????UserService?userService?=?
  58. ??????????
  59. ????????
  60. ????????MyInvocationHandler?invocationHandler?=?
  61. ??????????
  62. ????????
  63. ????????UserService?proxy?=?(UserService)?invocationHandler.getProxy();??
  64. ??????????
  65. ????????
  66. ????????proxy.add();??
  67. ??????????
  68. ????}??
  69. }??

执行结果如下:?------------------before------------------?--------------------add---------------?-------------------after------------------??? 用起来是很简单吧,其实这里基本上就是AOP的一个简单实现了,在目标对象的方法执行之前和执行之后进行了增强。Spring的AOP实现其实也是用了Proxy和InvocationHandler这两个东西的。???? 用起来是比较简单,但是如果能知道它背后做了些什么手脚,那就更好不过了。首先来看一下JDK是怎样生成代理对象的。既然生成代理对象是用的Proxy类的静态方newProxyInstance,那么我们就去它的源码里看一下它到底都做了些什么??

  1. ??????????????????????Class[]?interfaces,??
  2. ??????????????????????InvocationHandler?h)??
  3. ????
  4. ????{??
  5. ????
  6. ????????
  7. ????}??
  8. ??
  9. ????
  10. ????Class?cl?=?getProxyClass(loader,?interfaces);??
  11. ??
  12. ????
  13. ????
  14. ????????????
  15. ????????Constructor?cons?=?cl.getConstructor(constructorParams);??
  16. ????????????
  17. ????????
  18. ????}?
  19. ????????
  20. ????}?
  21. ????????
  22. ????}?
  23. ????????
  24. ????}?
  25. ????????
  26. ????}??
  27. ????}??

?? 我们再进去getProxyClass方法看一下?

    ?getProxyClass(ClassLoader?loader,???
  1. ?????????????????????????????????????????Class...?interfaces)??
  2. ????
  3. ????{??
  4. ????
  5. ?????
  6. ????????
  7. ????}??
  8. ??
  9. ????
  10. ????Class?proxyClass?=?
  11. ??
  12. ????String[]?interfaceNames?=?
  13. ??
  14. ????Set?interfaceSet?=?
  15. ??
  16. ????
  17. ????
  18. ??????????
  19. ????????
  20. ????????String?interfaceName?=?interfaces[i].getName();??
  21. ????????Class?interfaceClass?=?
  22. ????????
  23. ????????
  24. ????????interfaceClass?=?Class.forName(interfaceName,?
  25. ????????}?
  26. ????????}??
  27. ????????
  28. ????????
  29. ????????????interfaces[i]?+?
  30. ????????}??
  31. ??
  32. ????????
  33. ??????????
  34. ????????
  35. ????????interfaceSet.add(interfaceClass);??
  36. ??
  37. ????????interfaceNames[i]?=?interfaceName;??
  38. ????}??
  39. ??
  40. ????
  41. ????Object?key?=?Arrays.asList(interfaceNames);??
  42. ??
  43. ????Map?cache;??
  44. ??????
  45. ????
  46. ????????
  47. ????????cache?=?(Map)?loaderToCache.get(loader);??
  48. ????????
  49. ????????
  50. ????????cache?=?
  51. ????????
  52. ????????loaderToCache.put(loader,?cache);??
  53. ????????}??
  54. ??
  55. ????}??
  56. ??
  57. ????
  58. ??
  59. ????????
  60. ????????
  61. ????????Object?value?=?cache.get(key);??
  62. ????????
  63. ????????????proxyClass?=?(Class)?((Reference)?value).get();??
  64. ????????}??
  65. ????????
  66. ????????????
  67. ????????????
  68. ????????}?
  69. ????????????
  70. ????????????cache.wait();??
  71. ????????????}?
  72. ????????????}??
  73. ????????????
  74. ????????}?
  75. ????????????cache.put(key,?pendingGenerationMarker);??
  76. ????????????
  77. ????????}??
  78. ????????}?
  79. ????}??
  80. ??
  81. ????
  82. ????????
  83. ??????????
  84. ????????
  85. ????????
  86. ????????????proxyName,?interfaces);??
  87. ????????
  88. ????????????
  89. ????????????proxyClass?=?defineClass0(loader,?proxyName,??
  90. ????????????proxyClassFile,?
  91. ????????}?
  92. ????????????
  93. ????????}??
  94. ????????}??
  95. ????????
  96. ????????proxyClasses.put(proxyClass,?
  97. ??
  98. ????}???
  99. ????
  100. ??????
  101. ????
  102. ????}??

进去ProxyGenerator类的静态方法generateProxyClass,这里是真正生成代理类class字节码的地方。?

  1. ???????????????????????????????????????????Class[]?interfaces)??
  2. ???{??
  3. ???????ProxyGenerator?gen?=?
  4. ????
  5. ???????
  6. ??
  7. ????
  8. ???????
  9. ???????????java.security.AccessController.doPrivileged(??
  10. ???????????()?{??
  11. ???????????????
  12. ???????????????????
  13. ???????????????????????FileOutputStream?file?=??
  14. ???????????????????????????
  15. ???????????????????????file.write(classFile);??
  16. ???????????????????????file.close();??
  17. ???????????????????????
  18. ???????????????????}?
  19. ???????????????????????
  20. ???????????????????????????
  21. ???????????????????}??
  22. ???????????????}??
  23. ???????????});??
  24. ???????}??
  25. ??
  26. ????
  27. ???????
  28. ???}??

现在,JDK是怎样动态生成代理类的字节的原理已经一目了然了。?好了,再来解决另外一个问题,那就是由谁来调用InvocationHandler的invoke方法的。要解决这个问题就要看一下JDK到底为我们生成了一个什么东西。用以下代码可以获取到JDK为我们生成的字节码并写到硬盘中。?

  1. ??
  2. ??
  3. ??
  4. ??
  5. ????
  6. ????
  7. ????????
  8. ????????
  9. ??????????
  10. ????????
  11. ??????????
  12. ????????
  13. ????????
  14. ??????????
  15. ????????FileOutputStream?out?=?
  16. ??????????
  17. ????????
  18. ????????????out?=?
  19. ????????????out.write(classFile);??
  20. ????????????out.flush();??
  21. ????????}?
  22. ????????????e.printStackTrace();??
  23. ????????}?
  24. ????????????
  25. ????????????????out.close();??
  26. ????????????}?
  27. ????????????????e.printStackTrace();??
  28. ????????????}??
  29. ????????}??
  30. ????}??
  31. }??
  32. ??
  33. ??
  34. ??
  35. ??
  36. ????
  37. ????
  38. ????????
  39. ????????UserService?userService?=?
  40. ??????????
  41. ????????
  42. ????????MyInvocationHandler?invocationHandler?=?
  43. ??????????
  44. ????????
  45. ????????UserService?proxy?=?(UserService)?invocationHandler.getProxy();??
  46. ??????????
  47. ????????
  48. ????????proxy.add();??
  49. ??????????
  50. ????}??
  51. ??????
  52. ????
  53. ????
  54. ????????ProxyGeneratorUtils.writeProxyClassToHardDisk(
  55. ????}??
  56. }??

通过以上代码,就可以在F盘上生成一个$Proxy.class文件了,现在用反编译工具来看一下这个class文件里面的内容。?

  1. ??
  2. ??
  3. ????
  4. {??
  5. ??
  6. ????
  7. ????
  8. ????{??
  9. ????????
  10. ????}??
  11. ??
  12. ????
  13. ????{??
  14. ????????
  15. ????????{??
  16. ????????????
  17. ????????????????obj??
  18. ????????????})).booleanValue();??
  19. ????????}??
  20. ????????
  21. ????????
  22. ????????{??
  23. ????????????
  24. ????????}??
  25. ????}??
  26. ??
  27. ????
  28. ????
  29. ????{??
  30. ????????
  31. ????????{??
  32. ????????????
  33. ????????????
  34. ????????????
  35. ????????}??
  36. ????????
  37. ????????
  38. ????????{??
  39. ????????????
  40. ????????}??
  41. ????}??
  42. ??
  43. ????
  44. ????{??
  45. ????????
  46. ????????{??
  47. ????????????
  48. ????????}??
  49. ????????
  50. ????????
  51. ????????{??
  52. ????????????
  53. ????????}??
  54. ????}??
  55. ??
  56. ????
  57. ????{??
  58. ????????
  59. ????????{??
  60. ????????????
  61. ????????}??
  62. ????????
  63. ????????
  64. ????????{??
  65. ????????????
  66. ????????}??
  67. ????}??
  68. ??
  69. ????
  70. ????
  71. ????
  72. ????
  73. ??
  74. ????
  75. ????
  76. ????{??
  77. ????????
  78. ????????{??
  79. ????????????m1?=?Class.forName(
  80. ????????????????Class.forName(
  81. ????????????});??
  82. ????????????m3?=?Class.forName(
  83. ????????????m0?=?Class.forName(
  84. ????????????m2?=?Class.forName(
  85. ????????}??
  86. ????????
  87. ????????{??
  88. ????????????
  89. ????????}??
  90. ????????
  91. ????????{??
  92. ????????????
  93. ????????}??
  94. ????}??
  95. }??

好了,到目前为止,前面 的两个问题都已经知道回事了,现在再用JDK动态代理的时候就不只会用而已了,真正的达到了“知其然,知其所以然”的目的。。。

原文地址:http://rejoy.iteye.com/blog/1627405

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读