JDK动态代理的实现原理

水深无声 2022-11-19 04:04 440阅读 0赞

1、在JDK的java.lang.reflect包下有个Proxy类,他正是构造代理类的入口。

2、该类有一个方法newProxyInstance就是创建代理对象的方法。

3、这个方法需要3个参数:

  • ClassLoader,用来加载代理类的Loader类,通常这个Loader和被代理的类是同一个Loader类;
  • Interfaces,是要被代理的那些接口;
  • InvocationHandler,用于执行除了被代理接口中方法之外的用户自定义的操作,他也是用户需要代理的最终目的。用户调用目标方法都被代理到在InvocationHandler类中定义的唯一方法invoke()中。

4、下面开始贴代码

  1. package com.hl.chapter11.demo;
  2. /**
  3. * 需要动态代理的接口
  4. */
  5. public interface Target {
  6. /**
  7. * 你好
  8. *
  9. * @param name
  10. * @return
  11. */
  12. public String SayHello(String name);
  13. /**
  14. * 再见
  15. *
  16. * @return
  17. */
  18. public String SayGoodBye();
  19. }
  20. package com.hl.chapter11.demo;
  21. /**
  22. * 需要动态代理的实际对象
  23. */
  24. public class RealTarget implements Target {
  25. @Override
  26. public String SayHello(String name) {
  27. return "Hello " + name;
  28. }
  29. @Override
  30. public String SayGoodBye() {
  31. return "Good Bye";
  32. }
  33. }
  34. package com.hl.chapter11.demo;
  35. import java.lang.reflect.InvocationHandler;
  36. import java.lang.reflect.Method;
  37. /**
  38. * 调用处理器实现类
  39. * 每次生成动态代理类对象时都需要指定一个实现了该接口的调用处理器对象
  40. */
  41. public class MyInvocationHandler implements InvocationHandler {
  42. /**
  43. * 这个是我们代理的真实对象
  44. */
  45. private Object object;
  46. /**
  47. * 构造方法,给我们要代理的真实对象赋初值
  48. *
  49. * @param object
  50. */
  51. public MyInvocationHandler(Object object) {
  52. this.object = object;
  53. }
  54. /**
  55. * 该方法负责集中处理动态代理类上的所有方法调用
  56. * 动态代理类根据这三个参数进行预处理或分派到委托类实例上反射执行
  57. *
  58. * @param proxy 代理类实例
  59. * @param method 被调用的方法对象
  60. * @param args 调用参数
  61. * @return
  62. * @throws Throwable
  63. */
  64. @Override
  65. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  66. // 代理真实对象前的自定义操作
  67. System.out.println("----------------代理真实对象前的自定义操作------------------");
  68. System.out.println("Method: " + method);
  69. // 当代理对象调用真实对象的方法时,其会自动跳转到代理对象关联的handler对象的invoke方法进行调用
  70. Object returnObject = method.invoke(object, args);
  71. // 代理真实对象后的自定义操作,此处为代理的最终目的
  72. System.out.println("---------------代理真实对象后自定义操作-----------------");
  73. return returnObject;
  74. }
  75. }
  76. package com.hl.chapter11.demo;
  77. import java.lang.reflect.InvocationHandler;
  78. import java.lang.reflect.Proxy;
  79. /**
  80. * jdk动态代理演示
  81. */
  82. public class JdkDynamicProxyTest {
  83. public static void main(String[] args) {
  84. // 代理的真实对象
  85. Target realTarget = new RealTarget();
  86. /**
  87. * MyInvocationHandler 实现了 InvocationHandler 接口,并能实现方法调用从代理类到委托类的分派转发
  88. * 其内部通常包含指向委托类实例的引用,用于真正执行分派转发过来的方法调用.
  89. * 即:要代理哪个真实对象,就将该对象传进去,最后是通过该真实对象来调用其方法
  90. */
  91. InvocationHandler handler = new MyInvocationHandler(realTarget);
  92. // 获取类加载器
  93. ClassLoader classLoader = realTarget.getClass().getClassLoader();
  94. // 获取真实对象所实现的接口
  95. Class[] interfaces = realTarget.getClass().getInterfaces();
  96. /**
  97. * 该方法用户指定类加载器、一组接口、调用处理器来生成动态代理类实例
  98. */
  99. Target target = (Target) Proxy.newProxyInstance(classLoader, interfaces, handler);
  100. System.out.println("动态代理对象的类型:" + target.getClass().getName());
  101. String hello = target.SayHello("World");
  102. System.out.println(hello);
  103. String goodbye = target.SayGoodBye();
  104. System.out.println(goodbye);
  105. }
  106. }

5、执行结果如下:

  1. 动态代理对象的类型:com.sun.proxy.$Proxy0
  2. ----------------代理真实对象前的自定义操作------------------
  3. Method: public abstract java.lang.String com.hl.chapter11.demo.Target.SayHello(java.lang.String)
  4. ---------------代理真实对象后自定义操作-----------------
  5. Hello World
  6. ----------------代理真实对象前的自定义操作------------------
  7. Method: public abstract java.lang.String com.hl.chapter11.demo.Target.SayGoodBye()
  8. ---------------代理真实对象后自定义操作-----------------
  9. Good Bye
  10. Process finished with exit code 0

发表评论

表情:
评论列表 (有 0 条评论,440人围观)

还没有评论,来说两句吧...

相关阅读

    相关 JDK动态代理实现原理

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

    相关 jdk动态代理实现原理

    jdk动态代理实际上是jvm帮我们建成的类实现我们传入的接口,加载字节码到jvm。实际上就是帮我们拼接的字符串和我们传进去的接口进行拼接,然后生成字节码加载进虚拟机。代理类持有

    相关 jdk动态代理实现原理总结

    运行时创建一个代理对象的步骤为 1. 生成代理类的字节码 2. 加载字节码,创建代理对象 首先,代理对象的目的是在被调用方法的时候既能实现被代理对象的方法,又能够增加自