长梦留痕小说结局:java代理(Proxy)模式浅析

来源:百度文库 编辑:九乡新闻网 时间:2024/04/28 23:16:41
下面的代码实现一个简单的代理类,代码来自《java与模式》,该例子的任务是为一个Vector对象提供一个代理对象,当Vector的任何方法被调用之前和调用之后,分别打印出两条信息,这表明这个代理对象有能力截获和控制这个Vector对象。

  Java代码

  /*

  * 实现一个简单的代理类,代码来自《java与模式》该例子

  * 的任务是为一个Vector对象提供一个代理对象,当Vector

  * 的任何方法被调用之前和调用之后,分别打印出两条信息,

  * 这表明这个代理对象有能力截获和控制这个Vector对象。

  */

  public class VectorProxy implements InvocationHandler{

  //包含被代理的对象,这里是一个Vector

  private Object targetObj;

  //为被代理对象设置一个get方法,这里只是我用来测试所用

  public Object getTargetObj() {

  return targetObj;

  }

  //构造方法,并接受被代理对象作为参数

  public VectorProxy(Object targetObj) {

  this.targetObj = targetObj;

  }

  //一个静态工厂方法,用来获得代理对象,传递被代理对象作为参数

  public static Object factory(Object obj) {

  Class clazz = obj.getClass();

  //调用newProxyInstance方法得到一个代理对象,这个方法下面会详述

  Object proxy =  Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new VectorProxy(obj));

  return proxy;

  }

  //实现InvocationHandler接口的invoke方法,该方法会被自动调用

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

  throws Throwable {

  System.out.println("before invoke:" + method.getName()); //调用被代理对象某方法之前执行一句打印

  if(args != null) {

  for(Object o:args)

  System.out.println(o);

  }

  //通过代理对象获得被代理对象,首先调用Proxy的静态方法getInvocationHandler,并传递代理对象获得代理类中

  //关联的InvaocationHandler的实现类对象,再接着调用我们上面定义的获取被代理对象的get方法

  Object tarObj = ((VectorProxy)(Proxy.getInvocationHandler(proxy))).getTargetObj();

  System.out.println(tarObj == targetObj);  //测试通过上面方法获得的被代理对象是否就是当前VectorProxy实例中的对象

  Object resultObj = method.invoke(tarObj, args); //这里直接传递targetObj即可,对被代理对象调用某方法,并传递参数

  System.out.println("after invoke:" + method.getName());  //调用被代理对象某方法之后执行一句打印

  return resultObj;

  }

  public static void main(String[] args) {

  List v = null;

  //new Vector(10)是被代理对象,它被传入InvocationHandler中,作为成员变量,InvocationHandler的实现类也会作为Proxy的成员变量

  v = (List) factory(new Vector(10));

  //对代理对象调用被代理对象所拥有的方法,此时会自动调用Proxy中关联的VectorProxy实例的invoke方法

  v.add("NEW");

  System.out.println(v.get(0));

  }

  }

  上面的代码中我们创建类VectorProxy并实现InvocationHandler接口,当然它需要实现InvocationHandler接口中的invoke方法了。

  我们首先需要创建一个代理对象,并在代理对象中指定被代理对象,以及指定被代理对象的所有实现接口:

  Class clazz = obj.getClass(); //obj为被代理对象

  Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new VectorProxy(obj));  //传递三个参数:被代理对象的类加载器,被代理对象所实现的接口数组以及一个InvocationHandler实现类对象,注意这个实现类对象中包含了被代理对象。

  现在我们就用生成的代理对象来代替被代理对象,直接对代理对象进行操作。

  当Client需要调用被代理对象中的方法时,这些方法是它所实现接口中的方法( getInterfaces() ),此时我们是对代理对象调用这些方法,代理对象便会自动调用代理对象中相关联的InvocationHandler实现类的invoke方法,即我们实现的

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

  我们可以在invoke方法中实现我们需要的逻辑,包括调用被代理对象对应的方法:

  method.invoke(targetObject,args) //targetObject为被代理对象,被代理对象是作为InvocationHandler实现类的成员变量,args为传递给方法的参数,

  还可以在调用被代理对象相关方法之前和之后执行某些操作。

  当我们对代理对象执行某些操作,这些操作和对被代理对象执行的操作一样,其实我们的本意也是对被代理对象进行某些操作,在本例中,即在vector中添加,删除,获取对象等。此时会自动调用代理对象中相关联的InvocationHandler接口的实现类的invoke方法,同时将代理对象,被调用的方法以及方法的参数作为参数传递给invoke,因此我们便可以在invoke中实现我们需要的操作。

  JDK 中具体的动态代理类是怎么产生的呢?

  1.产生代理类$Proxy0 类

  执行了 Proxy. newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h)将产生$Proxy0 类,它继承Proxy 对象,并根据第二个参数,实现了被代理类的所有接口,自然就可以生成接口要实现的所有方法了(这时候会重写hashcode ,toString 和equals 三个方法),但是还没有具体的实现体;

  2.将代理类$Proxy0 类加载到JVM 中

  这时候是根据 Proxy. newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) 它的第一个参数---- 就是被代理类的类加载器,把当前的代理类加载到JVM 中

  3.创建代理类$Proxy0 类的对象

  调用的$Proxy0 类的$Proxy0 (InvocationHandler )构造函数,生成$Proxy0 类的对象

  参数就是 Proxy. newProxyInstance(ClassLoader loader, Class[] interfaces, InvocationHandler h) 它的第三个参数

  这个参数就是我们自己实现的InvocationHandler 对象,我们知道InvocationHandler 对象中组合加入了代理类代理的接口类的实现类;所以,$Proxy0 对象调用所有要实现的接口的方法,都会调用InvocationHandler 对象的invoke ()方法实现;

  4.生成代理类的class byte

  动态代理生成的都是二进制class 字节码