美文网首页
Java核心技术(卷I) 16、代理proxy

Java核心技术(卷I) 16、代理proxy

作者: kaiker | 来源:发表于2021-03-14 17:36 被阅读0次

1、书中的定义

书里的定义:利用代理可以在运行时创建实现了一组给定接口的新类。只有在编译时期无法确定需要实现哪个接口时才有必要使用代理。

  • 本书给的例子是:想构造一个类的对象,这个类实现了一些接口,但是编译的时候你不知道这些接口到底是什么。代理类可以在运行时创建全新的类,代理类能实现指定接口。

这个定义感觉比较难以理解。但是先看下代理要实现需要的几个要素。

构造一个代理对象需要三个参数:

  • 类加载器
  • 一个Class对象数组,每个元素对应需要实现的各个接口
  • 一个调用处理器,这个调用处理器是实现了InvocationHandler接口的类的对象,只有一个方法Object invoke(Object proxy, Method method Object[] args) 无论何时调用代理对象的方法,调用处理器的invoke方法都会被调用,并向其传递Method对象和原调用参数。

2、其他博客以及实例

看了下其他博客,大家大多给出的代理的用处是 代理的意义在于生成代理对象,在服务提供方和使用方之间充当一个媒介,控制真实对象的访问。
就是构造了这个代理对象后,你调用方法就会经过这个代理对象,这个代理对象就可以展开一些其他操作。
https://www.cnblogs.com/xdp-gacl/p/3971367.html
https://blog.csdn.net/weixin_43320847/article/details/82938754

结合上面两篇博客和书中的例子看,这是书中的例子

2.1 书中的例子

  • 调用处理器就是 TraceHandler 它代理的就是 private Object target
  • 构造代理对象的时候提供了三个参数 Object proxy = Proxy.newProxyInstance(null, new Class[] { Comparable.class } , handler);
  • 代理的对象实现了Compare接口
  • 在这个例子中Arrays.binarySearch(elements, key)会调用compareTo方法,但是elements存的是proxy对象,代理value这个对象,compareTo会经过handler 调用,调用的时候就会经过TraceHandler 里面invoke的一堆print,最后就会输出500.compareTo(x)这样的内容。如果elements里就存的value,那就什么都不会打印。
import java.lang.reflect.*;
import java.util.*;

/**
 * This program demonstrates the use of proxies.
 * @version 1.00 2000-04-13
 * @author Cay Horstmann
 */
public class ProxyTest
{
   public static void main(String[] args)
   {
      Object[] elements = new Object[1000];

      // fill elements with proxies for the integers 1 ... 1000
      for (int i = 0; i < elements.length; i++)
      {
         Integer value = i + 1;
         InvocationHandler handler = new TraceHandler(value);
         Object proxy = Proxy.newProxyInstance(null, new Class[] { Comparable.class } , handler);
         elements[i] = proxy;
      }

      // construct a random integer
      Integer key = new Random().nextInt(elements.length) + 1;

      // search for the key
      int result = Arrays.binarySearch(elements, key);

      // print match if found
      if (result >= 0) System.out.println(elements[result]);
   }
}

/**
 * An invocation handler that prints out the method name and parameters, then
 * invokes the original method
 */
class TraceHandler implements InvocationHandler
{
   private Object target;

   /**
    * Constructs a TraceHandler
    * @param t the implicit parameter of the method call
    */
   public TraceHandler(Object t)
   {
      target = t;
   }

   public Object invoke(Object proxy, Method m, Object[] args) throws Throwable
   {
      // print implicit argument
      System.out.print(target);
      // print method name
      System.out.print("." + m.getName() + "(");
      // print explicit arguments
      if (args != null)
      {
         for (int i = 0; i < args.length; i++)
         {
            System.out.print(args[i]);
            if (i < args.length - 1) System.out.print(", ");
         }
      }
      System.out.println(")");

      // invoke actual method
      return m.invoke(target, args);
   }
}

2.2 shop例子

https://blog.csdn.net/weixin_43320847/article/details/82938754

  • 代理的对象是 Shoping client 它实现的是Shopinng接口
  • 构造代理对象 Shopping shop = (Shopping) Proxy.newProxyInstance(Shopping.class.getClassLoader(), new Class[]{Shopping.class}, dyProxy);
  • 调用处理器 DynamicProxy
  • 最后shop.buy() 就不只是打印一句话,而是经过处理器,前后多打印一句话
interface Shopping {
    void buy();
}

// 例子中被代理的
class Client implements Shopping {
    public void buy() {
        System.out.println("我想买这件商品");
    }
}

// 调用处理器
public class DynamicProxy implements InvocationHandler {

    private Object target = null;

    DynamicProxy(Object target) {
        this.target = target;
    }

    /**
     * 代理方法逻辑
     *
     * @param proxy  代理对象
     * @param method 调度方法
     * @param args   调度方法参数
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理前");
        method.invoke(target, args);
        System.out.println("代理后");
        return null;
    }
}

public class DyProxyTest {
    public static void main(String[] args) {
        Shopping client = new Client();
        // 调用处理器
        DynamicProxy dyProxy = new DynamicProxy(client);
        // 构造代理对象
        Shopping shop = (Shopping) Proxy.newProxyInstance(Shopping.class.getClassLoader(), new Class[]{Shopping.class}, dyProxy);
        shop.buy();
    }
}

// 结果:
// 代理前
// 我想买这件商品
// 代理后

2.3 ldh例子

https://www.cnblogs.com/xdp-gacl/p/3971367.html

  • 代理的对象是 private Person ldh = new LiuDeHua();,实现的接口是Person
  • 调用p.sing("冰雨")的时候,就经过了handler,输出了额外的一些内容

相关文章

  • Java核心技术(卷I) 16、代理proxy

    1、书中的定义 书里的定义:利用代理可以在运行时创建实现了一组给定接口的新类。只有在编译时期无法确定需要实现哪个接...

  • 双11Java程序员书单推荐

    Java 《Java核心技术卷I》 《Java核心技术卷II》 《Java编程思想》 《Java并发编程实战》 《...

  • Java核心技术(卷I) 3、用户自定义类

    Java核心技术(卷I)关于类与对象基础 https://www.jianshu.com/p/36ba065d16...

  • 2021书单

    2021-01《活着》《如何阅读一本书》2021-11《Java核心技术卷I》《Java核心技术卷II》2021-...

  • 推书:Java核心技术 卷1 基础知识 原书第10版

    推书:Java核心技术 卷1 基础知识 原书第10版 《Java核心技术卷I》虽然该书很厚,有700多页,但知识体...

  • Java代理

    前言 Java代理大致可以分为静态代理(static proxy),动态代理(dynamic proxy)。所谓代...

  • Java核心知识

    Java核心语法 作者:springremember 书籍:《Java核心技术卷一》《Java核心技术卷二》 ja...

  • 记录一些书籍

    JAVA 基础 《Java核心技术·卷1:基础知识》《Java核心技术 卷2:高级特性》《Java8 实战》 并发...

  • Java SE基础部分

    Java核心语法 书籍:《Java核心技术卷一》《Java核心技术卷二》 java包结构:核心包,Java1一同出...

  • java反射和动态代理

    java动态代理Proxy.newProxyInstance 详解java代理机制(静态代理、动态代理)以及使用场景

网友评论

      本文标题:Java核心技术(卷I) 16、代理proxy

      本文链接:https://www.haomeiwen.com/subject/pfgxcltx.html