java反射の动态代理与静态代理

桃扇骨 2022-08-23 03:50 282阅读 0赞

静态代理弊端:

之前博客中有讲静态代理机制的,特征是代理类和目标对象的类都是在编译期间确定下来的,不利于程序的扩展。同时,每一个代理类只能为一个接口服务,这样一来程序开发中必然产生过多的代理

最好可以通过一个代理类完成全部代理功能

动态代理

定义

动态代理是指客户通过代理类来调用其他对象的方法,并且是在程序运行时根据需要动态创建目标类的代理对象。

使用场合

调试

远程方法调用

代理设计模式的原理

使用一个代理将对象包装起来(对象成为代理类属性),然后用该代理对象取代原始对象。任何对原始对象的调用都要通过代理,代理对象决定是否以及何时将方法调用转到原始对象上

3.动态代理--反射的应用,体会反射的动态性

静态代理:

要求被代理类和代理类同时实现相应的一套接口;

通过被代理类的对象调用重写接口的方法时,直接上执行的是被代理类的同样的方法调用

动态代理:

反射的动态性

在程序运行时根据被代理类及其实现的接口,动态的创建一个代理类,当调用代理类实现的抽象方法时,就发起对被代理类方法的调用。

技术点

实现了InvocationHandler接口实现类,并重写invoke()方法

Proxy.newInstance(obj.getClass.getClassLoader,obj.getClass().getInterfaces(),h); obj是被代理类的对象h是实现了InvocationHandler接口实现类的对象

  1. package myNetDemo;
  2. //静态代理模式
  3. //接口
  4. interface ClothesFactory {
  5. void productCloth();
  6. }
  7. // 被代理类
  8. class NikeClothFactory implements ClothesFactory {
  9. @Override
  10. public void productCloth() {
  11. System.out.println("Nike工厂生产衣服");
  12. }
  13. }
  14. // 代理类
  15. class ProxyFactory implements ClothesFactory {
  16. ClothesFactory cf;// 虽然声明的是总接口,但实例化时实际传进去的是具体被代理实现类
  17. // 在构造器内完成初始化
  18. public ProxyFactory(ClothesFactory cf) {
  19. this.cf = cf;
  20. }
  21. @Override
  22. public void productCloth() {
  23. System.out.println("代理类开始执行,收代理费");
  24. cf.productCloth();// 实际调用的是实际被代理类的实现方法
  25. }
  26. }
  27. public class TestProductClothes {
  28. public static void main(String[] args) {
  29. NikeClothFactory nikeClothFactory = new NikeClothFactory();// 创建被代理类的对象
  30. ProxyFactory pFactory = new ProxyFactory(nikeClothFactory);// 创建爱你代理类的对象
  31. pFactory.productCloth();// 实际调用的是被代理类方法
  32. // 若再有一个接口,还要在于一个接口的实现类(被代理类,目标类),在造一个代理类实现接口
  33. // 于是想要动态代理
  34. }
  35. }
  36. package myNetDemo;
  37. import java.lang.reflect.InvocationHandler;
  38. import java.lang.reflect.Method;
  39. import java.lang.reflect.Proxy;
  40. //动态代理的使用
  41. //反射式动态语言的关键,不在编译的时候,而是在运行的时候动态的创建被代理类
  42. interface Subject {
  43. void action();
  44. }
  45. // 被代理类
  46. class RealSubject implements Subject {
  47. @Override
  48. public void action() {
  49. System.out.println("我是被代理类");
  50. }
  51. }
  52. // 凡是与动态代理相关的必须要实现这个接口,实现这个接口的抽象方法
  53. class MyInvocationHandler implements InvocationHandler {
  54. Object obj;// 实现了接口的被代理类的对象的声明
  55. // 方法有两个作用①创建代理类时初始化被代理类对象②返回一个代理类对象
  56. // ①给被代理类的对象实例化②返回一个代理类的对象
  57. public Object blind(Object object) {
  58. this.obj = object;
  59. // ②返回一个代理类的对象()
  60. return Proxy.newProxyInstance(object.getClass().getClassLoader(),
  61. object.getClass().getInterfaces(), this);// h第三个参数,指的是实现了InvocationHandler接口的对象
  62. }
  63. // 当通过代理类的对象发起对被重写的方法的调用时,都对转化为对如下的invoke方法的调用
  64. @Override
  65. public Object invoke(Object proxy, Method method, Object[] args)
  66. throws Throwable {
  67. // 抽象方法的返回值,method方法的返回值.返回定义抽象接口的对象
  68. Object returnVal = method.invoke(obj, args);
  69. return returnVal;
  70. }
  71. }
  72. public class TestProxy {
  73. public static void main(String[] args) {
  74. //被代理类的对象
  75. RealSubject real=new RealSubject();
  76. //创建一个实现了InvacationHandler接口的对象
  77. MyInvocationHandler handler=new MyInvocationHandler();
  78. //调用blind方法,动态的返回一个同样实现了real所在类实现的接口Subject的代理类的对象
  79. Object obj=handler.blind(real);//返回定义接口的对象
  80. Subject sub=(Subject)obj;//此时的sub就是代理类的对象
  81. sub.action();//转到对InvacationHandler实现类的invoke方法的调用
  82. //在举一例
  83. NikeClothFactory nike=new NikeClothFactory();
  84. ClothesFactory proxyCloth=(ClothesFactory)handler.blind(nike);//proxyCloth即为代理类的对象
  85. proxyCloth.productCloth();
  86. }
  87. }

发表评论

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

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

相关阅读

    相关 java反射动态代理静态代理

    静态代理弊端: 之前博客中有讲静态代理机制的,特征是代理类和目标对象的类都是在编译期间确定下来的,不利于程序的扩展。同时,每一个代理类只能为一个接口服务,这样一来程序开发中必

    相关 静态代理动态代理

               记得刚接触代理,是在大话设计模式,最近在技术总结和学些java的过程又接触到静态代理和动态代理,尤其是动态代理,在学习AOP时,用到了动态代理,下面我用