【Java基础】代理 - Proxy

来源:互联网 发布:mac如何删除qq浏览器 编辑:程序博客网 时间:2024/06/05 19:58

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

代理类是在程序运行过程中创建的。然而,一旦被创建,就变成了常规类,与虚拟机中的任何其他类没有什么区别。

对于特定的类加载器和预设的一组接口来说,只能有一个代理类。也就是说,如果使用同一个类加载器和接口数组调用两次newProxyInstance方法的话,只能够得到同一个类的两个对象。


代理实际上就是java.lang.reflect.Proxy动态地根据所指定的接口生成的class byte。该类会继承Proxy类,并实现所有指定的接口(interfaces参数),最后使用参入的class loader将class byte加载如系统,生成这样的一个类的对象。

在最后的一个示例中,可以看到生成的代理类的继承体系及实现的接口。

代理类 - Proxy

public class Proxy extends Object implements Serializable (java.lang.reflect)

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

static ObjectnewProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

Returns an instance of a proxy class for the specified interfaces that dispatches method invocations to the specified invocation handler.

  • 一个类加载器:作为Java安全模型的一部分,对于系统类和从因特网上下载来的类,可以使用不同的类加载器。使用null表示使用默认的类加载器(系统类的加载器)。
  • 一个Class对象数组,每个元素都是需要实现的接口。
  • 一个调用处理器。

调用处理器 - InvocationHandler

public interface InvocationHandler (java.lang.reflect)

Modifier and TypeMethod and DescriptionObjectinvoke(Object proxy, Method method, Object[] args)

Processes a method invocation on a proxy instance and returns the result.
该方法定义了代理对象调用方法时希望执行的动作。

当调用代理类时,代理类只会调用InvocationHandler的invoke方法,所以真正实现的方法必须在invoke方法中去调用。


示例

系统接口代理

Integer类实现了Comparable接口。

import java.util.*;import java.lang.reflect.*;public class ProxyTest {    public static void main(String[] args){    Object[] elements = new Object[100];        // fill elements with proxies for the integer    for (int i = 0; i < elements.length; i++){     Integer value = i + 1;     Class[] interfaces = value.getClass().getInterfaces();     InvocationHandler handler = new TraceHandler(value);     Object proxy = Proxy.newProxyInstance(null, interfaces, 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);        if (result >= 0){     System.out.println(elements[result]);    }    }}class TraceHandler implements InvocationHandler{private Object target;public TraceHandler(Object t){target = t;}public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {// print the invoked method infoSystem.out.print("Proxy invoke: ");System.out.print(target);System.out.print("." + m.getName() + "(");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 methodreturn m.invoke(target, args);}}


自定义接口代理

import java.util.*;import java.lang.reflect.*;public class ProxyTest2 {    public static void main(String[] args){        TestClass testClass = new TestClass();     Class[] interfaces = testClass.getClass().getInterfaces();     InvocationHandler handler = new TraceHandler2(testClass);     Object proxy = Proxy.newProxyInstance(testClass.getClass().getClassLoader(), interfaces, handler);     ((TestInterface)proxy).test();     //((TestClass)proxy).test();   error; Proxy cannot be cast to TestClass     //((TestClass)proxy).test2();  error; Proxy cannot be cast to TestClass    }}interface TestInterface{void test();}class TestClass implements TestInterface{    public void test(){    System.out.println("TestClass.test");    }      public void test2(){    System.out.println("TestClass.test2");    }        public String toString(){    return "TestClass Instance";    }}class TraceHandler2 implements InvocationHandler{private Object target;public TraceHandler2(Object t){target = t;}public Object invoke(Object proxy, Method m, Object[] args) throws Throwable {// print the invoked method infoSystem.out.print("Proxy invoke: ");System.out.print(target);System.out.print("." + m.getName() + "(");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 methodreturn m.invoke(target, args);}}

打印代理类

我们使用反射中的打印类信息的方法,查看上面示例中生成的代理类的定义:

public class ReflectionTest{public static void main(String[] args){            TestClass testClass = new TestClass();            Class[] interfaces = testClass.getClass().getInterfaces();            InvocationHandler handler = new TraceHandler2(testClass);            Object proxy = Proxy.newProxyInstance(testClass.getClass().getClassLoader(), interfaces, handler);            ClassAnalyzer.printClass(proxy.getClass());}}

输出:



0 0
原创粉丝点击