• 【Java高级技术】动态代理


    动态代理

    1.程序为什么需要代理?

    对象如果觉得自己干的事太多,可以通过代理转移一部分职责

    2.代理要具备什么功能?

    对象有什么方法想被代理,代理就一定要有对应的方法

    Java通过接口(接口中提供被代理对象的抽象功能,由代理实现即可)来保证代理的样子

    3.如何为Java创建一个代理对象
    • java.lang.reflect.Proxy类:提供了为对象产生代理对象的方法

      public static Object newProxyInstance(ClassLoader loader,Class<?>[] interface,InvocationHandler h)
      
      • 1
    • 参数一:loader:类加载器,作用是加载代理类

    • 参数二:interfaces:代理接口包含的内容,为数组形式

    • 参数三:h:传递InvocationHandler的实现类对象,用来指定代理对象的具体功能

    • 通过invokehandler的invoke方法指定代理干的事,这个invoke会被代理的方法在底层回调,参数需要接收(被代理的对象,invoke调用者所需要的参数(数组形式)

    4.案例
    • 定义Star接口(保证代理的样子):提供抽象方法,表示需要代理的方法

      public interface Star {
          /**
           * @param songName 歌名
           * @return 唱完歌的反馈
           */
          public abstract String sing(String songName);
      
          /**
           * 跳舞,无参无返
           */
          public abstract void dance();
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
    • 定义BigStar类:实现Star接口,重写Star中的抽象方法

      提供成员变量name,提供sing和dance方法

      public class BigStar implements Star {
      
          private String name;
      
          public BigStar(String name) {
              this.name = name;
          }
      
          @Override
          public String sing(String songName) {
              System.out.println(name + "正在唱:" + songName);
              return "谢谢大家~"; //唱完歌的反馈
          }
      
          @Override
          public void dance() {
              System.out.println(name + "正在优美的跳舞~");
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
    • 定义ProxyUtil类:提供静态方法创建代理,接收被代理对象(BigStar),多态返回代理对象Star

      (1)java提供的为对象创建代理的方法(三个参数)Proxy.newProxyInstance

      (2)重写后的invoke方法:用来指定代理对象的具体功能(回调方法:被sing和dance在底层调用)

      (3)返回代理对象

      public class ProxyUtil {
          public static Star createProxy(BigStar bigStar) {
              //java提供的为对象创建代理的方法(三个参数)
              Star starProxy = (Star) Proxy.newProxyInstance(
                      ProxyUtil.class.getClassLoader(),   //类加载器,作用是加载代理类
                      new Class[]{Star.class},            //代理接口包含的内容,为数组形式
                      new InvocationHandler() {        //InvocationHandler的实现类对象,用来指定代理对象的具体功能
             
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                              //Object proxy:代理对象
                              //Method method:invoke的调用者,可能是sing方法,也可能是dance方法
                              //Object[] args:invoke调用者所需要的参数(数组形式)
      
                              //判断当前invoke的调用者
                              if (method.getName().equals("sing")) {
                                  //代理要做的事
                                  System.out.println("准备话筒,收钱..");
                              }else if(method.getName().equals("dance")){
                                  //代理要做的事
                                  System.out.println("准备场地,收钱..");
                              }
                              //代理做了该做的,剩余都由本尊做
                              return method.invoke(bigStar, args);
                          }
                      }
              );
      
              //返回代理对象
              return starProxy;
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
    • 测试类:通过ProxyUtil类获取代理对象,调用被代理的方法(sing、dance)

      public class Test {
          public static void main(String[] args) {
              Star starProxy = ProxyUtil.createProxy(new BigStar("周杰伦"));
              String result = starProxy.sing("晴天");
              System.out.println(result);
              System.out.println("--------------");
              starProxy.dance();
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
  • 相关阅读:
    virtio frontend and backend
    Linux apt命令详解
    NEFTUNE: NOISY EMBEDDINGS IMPROVE INSTRUCTION FINETUNING
    SparkSQL---简介及RDD V.S DataFrame V.S Dataset编程模型详解
    基于双级阈值及过零率的语音激活检测(VAD)
    源码安装nginx及其配置
    基于Open vSwitch的传统限速和SDN限速--实验
    [附源码]java毕业设计网上购物商城
    Java23种设计模式-创建型模式之抽象工厂模式
    在vscode运行java代码
  • 原文地址:https://blog.csdn.net/m0_65462447/article/details/133590159