java-代理(proxy)

84 阅读1分钟

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

使用代理

代理类能够实现指定的接口。它具有下列方法 :

  • 指定接口所需要的全部方法
  • Object类中的全部方法,例如 toString 、 equals 等

调用处理器是实现了 InvocationHandler 接口的类对象 。 在这个接口中只有一个方法 :

 Object invoke ( Object proxy , Method method , Object[]args )

创建代理对象

要想创建一个代理对象 , 需要使用 Proxy 类的 newProxylnstance 方法 。 这个方法有三个参数 :

  • 一个类加栽器 ( class loader ) 。用 null 表示使用默认的类加载器
  • 一个 Class 对象数组 , 每个元素都是需要实现的接口 。
  • 一个调用处理器

使用代理场景:

  • 路由对远程服务器的方法调用
  • 在程序运行期间, 将用户接口事件与动作关联起来 。
  • 为调试 ,跟踪方法调用

一个调用二分查找并在代理中invoke方法中打印参数和方法名称的示例代码:

public class TestProxy {
    public static void main(String[] args) {
        Class<?>[] interfaces = new Class<?>[]{Comparable.class};

        Object[] elements = new Object[1000];
        for(int i=0;i< elements.length;i++){
            Integer va = i+1;
            elements[i]=Proxy.newProxyInstance(null,interfaces,new TraceHandler(va));
        }
        int result = Arrays.binarySearch(elements, 288);
        System.out.println("result:"+elements[result]);
    }
}


class TraceHandler implements InvocationHandler{

    final private Object target;
    TraceHandler(Object  target){
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.print(target);
        System.out.print("."+method.getName());
        if(args!=null){
            for(Object o:args){
                System.out.print(","+o);
            }
        }

        System.out.println();
        return method.invoke(target,args);
    }
}

程序输出结果:

500.compareTo,288
250.compareTo,288
375.compareTo,288
312.compareTo,288
281.compareTo,288
296.compareTo,288
288.compareTo,288
288.toString
result:288