java

当前位置:中华考试网 >> java >> java教程 >> 文章内容

使用Proxy模式及Java内建的动态代理机制

来源:中华考试网  [2020年12月3日]  【

  1.Proxy模式

  代理模式支持将某些操作从实际的对象中分离出来,通过它的代理类提供处理。这样便于修改和管理这些特定的操作。

  <>Subject.java

  package com.zj.proxy;

  public interface Subject {

  void operation1();

  void operation2(String arg);

  }

  现实类RealSubject.java

  package com.zj.proxy;

  public class RealSubject implements Subject {

  public void operation1() {

  System.out.println("Realer do operation1");

  填写下面表单即可预约申请免费试听java课程!害怕学不会?助教陪读,随时解惑!担心就业?一地学习,可全国推荐就业!

  }

  public void operation2(String arg) {

  System.out.println("Realer do operation2 with " + arg);

  }

  }

  代理类ProxySubject.java

  package com.zj.proxy;

  public class ProxySubject implements Subject {

  private Subject proxied;// 被代理对象

  public ProxySubject(Subject proxied) {

  this.proxied = proxied;

  }

  public void operation1() {

  System.out.println("Proxyer do operation1");

  proxied.operation1();

  }

  public void operation2(String arg) {

  System.out.println("Proxyer do operation2 with " + arg);

  proxied.operation2(arg);

  }

  }

  测试类SimpleProxyDemo.java

  package com.zj.proxy.client;

  import com.zj.proxy.Subject;

  import com.zj.proxy.RealSubject;

  import com.zj.proxy.ProxySubject;

  public class SimpleProxyDemo {

  public static void consumer(Subject subject) {

  subject.operation1();

  subject.operation2("ZJ");

  }

  public static void main(String[] args) {

  RealSubject real = new RealSubject();

  System.out.println("===Without Proxy===");

  consumer(real);

  System.out.println("===Use Proxy===");

  consumer(new ProxySubject(real));

  }

  }

  结果:

  ===Without Proxy===

  Realer do operation1

  Realer do operation2 with ZJ

  ===Use Proxy===

  Proxyer do operation1

  Realer do operation1

  Proxyer do operation2 with ZJ

  Realer do operation2 with ZJ

  2.使用Java的动态代理机制

  设计一个类用于实现InvocationHandle接口,InvocationHandler 是代理实例的调用处理程序实现的接口。

  每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法。

  <>InvocationHandle.java

  package java.lang.reflect;

  public interface InvocationHandler {

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

  throws Throwable;

  }

  对应invoke参数:

  [1]proxy - 在其上调用方法的代理实例;

  [2]method - 对应于在代理实例上调用的接口方法的 Method 实例;

  [3]args - 包含传入代理实例上方法调用的参数值的对象数组,如果接口方法不使用参数,则为 null。

  现在设计一个类实现该接口,并提供代理实例。

  DynamicProxyHandler.java

  package com.zj.proxy.dynamic;

  import java.lang.reflect.InvocationHandler;

  import java.lang.reflect.Method;

  public class DynamicProxyHandler implements InvocationHandler {

  private Object proxied;

  public DynamicProxyHandler(Object proxied) {

  this.proxied = proxied;

  }

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

  throws Throwable {

  System.out.println("**** proxy: ****\n" + proxy.getClass()

  + "\nmethod: " + method + "\nargs: " + args);

  if (args != null)

  for (Object arg : args)

  System.out.println(" " + arg);

  return method.invoke(proxied, args);

  }

  }

  这里的private Object proxied;即代理实例,也即上文代理模式中介绍的RealSubject对象。

  在invoke()方法中,我们会打印它的所有参数,并调用当前代理的方法。

  测试类DynamicProxyDemo.java

  package com.zj.proxy.client;

  import java.lang.reflect.Proxy;

  import com.zj.proxy.Subject;

  import com.zj.proxy.RealSubject;

  import com.zj.proxy.dynamic.DynamicProxyHandler;

  public class DynamicProxyDemo {

  public static void consumer(Subject subject) {

  subject.operation1();

  subject.operation2("ZJ");

  }

  public static void main(String[] args) {

  RealSubject real = new RealSubject();

  System.out.println("===Without Proxy===");

  consumer(real);

  System.out.println("===Use Proxy===");

  Subject proxy = (Subject) Proxy.newProxyInstance(Subject.class

  .getClassLoader(), new Class[] { Subject.class },

  new DynamicProxyHandler(real));

  consumer(proxy);

  }

  }

  这里通过Proxy的静态方法newProxyInstance(ClassLoader loader, Class[] interfaces,InvocationHandler h)生成代理类,并传递与其关联的调用处理程序new DynamicProxyHandler(real)。

  对于newProxyInstance()的参数:

  [1]loader - 定义代理类的类加载器 ;

  [2]interfaces - 代理类要实现的接口列表 ;

  [3]h - 指派方法调用的调用处理程序 。

  测试结果:

  ===Without Proxy===

  Realer do operation1

  Realer do operation2 with ZJ

  ===Use Proxy===

  **** proxy: ****

  class $Proxy0

  method: public abstract void com.zj.proxy.Subject.operation1()

  args: null

  Realer do operation1

  **** proxy: ****

  class $Proxy0

  method: public abstract void com.zj.proxy.Subject.operation2(java.lang.String)

  args: [Ljava.lang.Object;@de6f34

  ZJ

  Realer do operation2 with ZJ

  从结果可以发现,通过代理可以得到当前被调用的方法,及其参数。代理过程可以基于此进行逻辑处理,测试程序只是简单的打印这些相关信息。

  如果你现在想学习Java,赢取高薪工作机会,非常简单,填写下面信息,学好Java技术高薪工作机会唾手可得。

责编:fushihao
  • 会计考试
  • 建筑工程
  • 职业资格
  • 医药考试
  • 外语考试
  • 学历考试