JAVA动态代理

静态代理

在介绍动态代理之前,我们先来看看静态代理的实现过程,代理我们可以理解为为其他对象提供一种代理以控制对这个对象的访问。

首先我们创建一个接口:

public interface Animal
{
   public void sleep();
   public void run();
}

接下来,我们创建一个实现类:

public class Dog implements Animal
{

   @Override
   public void sleep()
   {
      System.out.println("dog sleep...");
   }

   @Override
   public void run()
   {
      System.out.println("dog run...");
   }
}

我们现在要对Dog类进行代理,所以需要创建代理类:

package dynamicproxy;

public class DogProxy implements Animal
{
   private Animal animal = null;

   public DogProxy(Animal animal)
   {
      this.animal = animal;
   }

   @Override
   public void sleep()
   {
      System.out.println("before invoke sleep...");
      animal.sleep();
      System.out.println("after invoke sleep...");
   }

   @Override
   public void run()
   {
      System.out.println("before invoke run...");
      animal.run();
      System.out.println("after invoke run...");
   }
}

下面我们用一个测试类测试一下:

package dynamicproxy;

public class Test
{
   public static void main(String[] args) throws Exception
   {
      Animal animal = new DogProxy(new Dog());
      animal.sleep();
      animal.run();
   }
}

运行结果:
before invoke sleep…
dog sleep…
after invoke sleep…
before invoke run…
dog run…
after invoke run…

动态代理

静态代理存在大量的重复代码且需要维护多个代理类,维护成本很大,所以使用动态代理是很有必要的。

动态代理需要用到java.lang.reflect.InvocationHandlerjava.lang.reflect.Proxy
InvocationHandler是代理实例的调用处理程序 实现的接口。Proxy提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。

同样的我们还是以静态代理中的例子来演示动态代理的使用,实现同样的功能,我们可以编写一个类实现InvocationHandler接口:

package dynamicproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class AnimalInvocationHandler implements InvocationHandler
{
   private Object targetObject = null;

   public Object bind(Object targetObject)
   {
      this.targetObject = targetObject;
      return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
            targetObject.getClass().getInterfaces(), this);
   }

   @Override
   public Object invoke(Object proxy, Method method, Object[] args)
         throws Throwable
   {
      String name = method.getName();
      System.out.println("before invoke " + name + "...");
      Object result = method.invoke(targetObject, args);
      System.out.println("after invoke " + name + "...");
      return result;
   }
}

最后,我们编写一个测试类测试一下:

public class Test
{
   public static void main(String[] args) throws Exception
   {
      AnimalInvocationHandler invocationHandler = new AnimalInvocationHandler();
      Animal animal = (Animal) invocationHandler.bind(new Dog());
      animal.sleep();
      animal.run();
   }
}

运行结果:
before invoke sleep…
dog sleep…
after invoke sleep…
before invoke run…
dog run…
after invoke run…

通过对比动态代理与静态代理的实现方式,我们可以发现动态代理更加简洁,更易于维护。

我们可以将动态代理的相关实现提取出来,形成工具类,方便以后使用:

import java.lang.reflect.Method;

/**
 * 动态代理支持接口
 *
 * @author jianggujin
 *
 */
public interface DynamicProxySupport
{
   /**
    * 方法执行前执行
    *
    * @param backIfFalse
    *           如果不继续执行的返回数据
    * @param delegate
    *           委托对象
    * @param proxy
    *           代理对象
    * @param method
    *           要执行的委托对象的方法
    * @param args
    *           要执行的委托对象的方法的参数
    * @return true 继续向下执行,否则不执行
    */
   public boolean beforeInvoke(Object backIfFalse, Object delegate,
         Object proxy, Method method, Object[] args);

   /**
    * 方法执行后执行
    *
    * @param result
    *           要执行的委托对象的方法的结果
    * @param delegate
    *           委托对象
    * @param proxy
    *           代理对象
    * @param method
    *           要执行的委托对象的方法
    * @param args
    *           要执行的委托对象的方法的参数
    */
   public void afterInvoke(Object result, Object delegate, Object proxy,
         Method method, Object[] args);
}
import java.lang.reflect.Method;

/**
 * 动态代理支持接口实现类,实现代理指定方法,方法规则为
 * {@link #beforeMethodInvoke(Object, Object, Object, Object[])}
 * ,返回类型为Boolean(boolean)或
 * {@link #afterMethodInvoke(Object, Object, Object, Object[])},返回类型为void(不做拦截)
 * ,分别用于方法前与方法后执行,其中Method为实际需要代理的方法名,且方法首字母大写
 *
 * @author jianggujin
 *
 */
public class MethodDynamicProxy implements DynamicProxySupport
{
   private final String BEFORE = "before%c%sInvoke";
   private final String AFTER = "after%c%sInvoke";
   private final Class<?> OBJ_ARRAY = new Object[0].getClass();

   /**
    * 获得需要执行的方法
    *
    * @param format
    * @param method
    * @return
    * @throws NoSuchMethodException
    */
   private Method getInvokeMethod(String format, Method method)
         throws NoSuchMethodException
   {
      String methodName = method.getName();
      Method invokeMethod = this.getClass()
            .getMethod(
                  String.format(format, Character.toUpperCase(methodName
                        .charAt(0)), methodName.length() == 1 ? "" : method
                        .getName().substring(1)), Object.class, Object.class,
                  Object.class, OBJ_ARRAY);
      return invokeMethod;
   }

   public boolean beforeInvoke(Object backIfFalse, Object delegate,
         Object proxy, Method method, Object[] args)
   {
      try
      {
         Method before = getInvokeMethod(BEFORE, method);
         if (!before.getReturnType().getSimpleName()
               .equalsIgnoreCase("boolean"))
         {
            throw new Exception("the method " + before.getName()
                  + "return type is not Boolean");
         }
         return (Boolean) before.invoke(this, backIfFalse, delegate, proxy,
               args);
      }
      catch (NoSuchMethodException e)
      {
      }
      catch (Exception e)
      {
         throw new RuntimeException(e);
      }
      return true;
   }

   public void afterInvoke(Object result, Object delegate, Object proxy,
         Method method, Object[] args)
   {
      try
      {
         Method after = getInvokeMethod(AFTER, method);
         after.invoke(this, result, delegate, proxy, args);
      }
      catch (NoSuchMethodException e)
      {
      }
      catch (Exception e)
      {
         throw new RuntimeException(e);
      }
   }
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 动态代理,获得委托对象的代理对象
 *
 * @author jianggujin
 *
 * @param <P>
 *           接口
 * @param <C>
 *           实现类
 */
public class DynamicProxy<P, C> implements InvocationHandler
{
   /** 委托对象 **/
   private Object delegate;
   /** 动态代理支持接口 **/
   private DynamicProxySupport dynamicProxySupport = null;

   /**
    * 返回指定类的代理对象,通过默认构造方法创建委托对象
    *
    * @param clazz
    *           委托对象类
    * @return <P>
    *         p
    * @throws InstantiationException
    * @throws IllegalAccessException
    */
   @SuppressWarnings("unchecked")
   public P bind(Class<C> clazz) throws InstantiationException,
         IllegalAccessException
   {
      this.delegate = clazz.newInstance();
      // 取得代理对象
      return (P) Proxy.newProxyInstance(clazz.getClassLoader(),
            clazz.getInterfaces(), this);
   }

   /**
    * 返回指定类的代理对象,通过默认构造方法创建委托对象
    *
    * @param clazz
    *           委托对象类
    * @return <P>
    *         p
    * @throws InstantiationException
    * @throws IllegalAccessException
    */
   @SuppressWarnings("unchecked")
   public P bind(Class<C> clazz, DynamicProxySupport dynamicProxySupport)
         throws InstantiationException, IllegalAccessException
   {
      this.delegate = clazz.newInstance();
      this.dynamicProxySupport = dynamicProxySupport;
      // 取得代理对象
      return (P) Proxy.newProxyInstance(clazz.getClassLoader(),
            clazz.getInterfaces(), this);
   }

   /**
    * 绑定委托对象并返回一个代理对象
    *
    * @param target
    * @return <P>
    *         p
    */
   @SuppressWarnings("unchecked")
   public P bind(C target)
   {
      this.delegate = target;
      // 取得代理对象
      return (P) Proxy.newProxyInstance(target.getClass().getClassLoader(),
            target.getClass().getInterfaces(), this);
   }

   /**
    * 绑定委托对象并返回一个代理对象
    *
    * @param target
    * @return <P>
    *         p
    */
   @SuppressWarnings("unchecked")
   public P bind(C target, DynamicProxySupport dynamicProxySupport)
   {
      this.delegate = target;
      this.dynamicProxySupport = dynamicProxySupport;
      // 取得代理对象
      return (P) Proxy.newProxyInstance(target.getClass().getClassLoader(),
            target.getClass().getInterfaces(), this);
   }

   /**
    * 执行方法
    *
    * @param proxy
    *           代理对象
    * @param method
    *           要执行的委托对象的方法
    * @param args
    *           要执行的委托对象的方法的参数
    */
   public Object invoke(Object proxy, Method method, Object[] args)
         throws Throwable
   {
      Object result = null;
      if (dynamicProxySupport != null)
      {
         Object obj = new Object();
         if (dynamicProxySupport.beforeInvoke(obj, delegate, proxy, method,
               args))
         {
            result = method.invoke(delegate, args);
            dynamicProxySupport.afterInvoke(result, delegate, proxy, method,
                  args);
         }
         else
         {
            return obj;
         }
      }
      else
      {
         result = method.invoke(delegate, args);
      }
      return result;
   }

   /**
    * 获得动态代理支持接口
    *
    * @return dynamicProxySupport
    */
   public DynamicProxySupport getDynamicProxySupport()
   {
      return dynamicProxySupport;
   }

   /**
    * 设置动态代理支持接口
    *
    * @param dynamicProxySupport
    */
   public void setDynamicProxySupport(DynamicProxySupport dynamicProxySupport)
   {
      this.dynamicProxySupport = dynamicProxySupport;
   }

   /**
    * 获得委托对象
    *
    * @return <C> c
    */
   @SuppressWarnings("unchecked")
   public C getDelegate()
   {
      return (C) delegate;
   }
}

我们可以这样使用工具类

import java.lang.reflect.Method;

public class Test
{
   public static void main(String[] args) throws Exception
   {
      DynamicProxy<Animal, Dog> dynamicProxy = new DynamicProxy<Animal, Dog>();
      Animal animal = dynamicProxy.bind(Dog.class, new DynamicProxySupport()
      {

         @Override
         public boolean beforeInvoke(Object backIfFalse, Object delegate,
               Object proxy, Method method, Object[] args)
         {
            System.out.println("before invoke " + method.getName());
            return true;
         }

         @Override
         public void afterInvoke(Object result, Object delegate, Object proxy,
               Method method, Object[] args)
         {
            System.out.println("after invoke " + method.getName());
         }
      });
      animal.sleep();
      animal.run();
   }
}

运行结果:
before invoke sleep
dog sleep…
after invoke sleep
before invoke run
dog run…
after invoke run

如果我们想代理指定的方法,我们可以这样去写:

package dynamicproxy;

public class Test
{
   public static void main(String[] args) throws Exception
   {
      DynamicProxy<Animal, Dog> dynamicProxy = new DynamicProxy<Animal, Dog>();
      Animal animal = dynamicProxy.bind(Dog.class, new MethodDynamicProxy()
      {
         public boolean beforeSleepInvoke(Object backIfFalse, Object delegate,
               Object proxy, Object[] args)
         {
            System.out.println("before invoke sleep");
            return false;
         }

         public boolean beforeRunInvoke(Object backIfFalse, Object delegate,
               Object proxy, Object[] args)
         {
            System.out.println("before invoke run");
            return true;
         }

         public void afterSleepInvoke(Object backIfFalse, Object delegate,
               Object proxy, Object[] args)
         {
            System.out.println("after invoke sleep");
         }

         public void afterRunInvoke(Object backIfFalse, Object delegate,
               Object proxy, Object[] args)
         {
            System.out.println("after invoke run");
         }
      });
      animal.sleep();
      animal.run();
   }
}

运行结果:
before invoke sleep
before invoke run
dog run…
after invoke run

时间: 2024-08-02 09:38:11

JAVA动态代理的相关文章

Java动态代理机制分析及扩展,第2部分

本文希望将 Java 动态代理机制从接口扩展到类,使得类能够享有与接口类 似的动态代理支持. 设计及特点 新扩展的类名为 ProxyEx,将直接继承于 java.lang.reflect.Proxy,也声 明了与原 Proxy 类中同名的 public 静态方法,目的是保持与原代理机制在使 用方法上的完全一致. 图 1. ProxyEx 类继承图 与原代理机制最大的区别在于,动态生成的代理类将不再从 Proxy 类继承, 改而继承需被代理的类.由于 Java 的单继承原则,扩展代理机制所支持的类

Java动态代理机制分析及扩展,第1部分

引言 Java 动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要 简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所 有的方法调用分派到委托对象上反射执行,在分派执行的过程中,开发人员还可 以按需调整委托类对象及其功能,这是一套非常灵活有弹性的代理框架.通过阅 读本文,读者将会对 Java 动态代理机制有更加深入的理解.本文首先从 Java 动态代理的运行机制和特点出发,对其代码进行了分析,推演了动态生成类的内 部实现. 代理:设计模式 代理是一种常用的设

Java 动态代理机制分析及扩展

简介: 本文通过分析 Java 动态代理的机制和特点,解读动态代理类的源代码,并且模拟推演了动态代理类的可能实现,向读者阐述了一个完整的 Java 动态代理运作过程,希望能帮助读者加深对 Java 动态代理的理解和应用. 引言 Java 动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类.代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过程中,开发人员还可以按需调整委托类对象及其功能,这是一套非常灵活有弹性的

java动态代理-如何理解Java的动态代理?

问题描述 如何理解Java的动态代理? Java的动态代理怎么理解? 哪位高手能详细解释一下这个问题,最好举个例子吧. 解决方案 彻底理解JAVA动态代理http://www.cnblogs.com/flyoung2008/archive/2013/08/11/3251148.html 解决方案二: Java动态代理详解

详解java动态代理模式_java

本文针对java动态代理进行知识点整理,具体内容如下 一. JAVA的动态代理(比较官方说法) 代理模式是常用的java设计模式,他的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处 理消息.过滤消息.把消息转发给委托类,以及事后处理消息等. 代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的 对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提 供特定的服务. 按照代理的创建时期,代理类可以分为两种. 静态代理:由程序员创建或特定工

详解Java动态代理的实现机制_java

一.概述 代理是一种设计模式,其目的是为其他对象提供一个代理以控制对某个对象的访问,代理类负责为委托类预处理消息,过滤消息并转发消息以及进行消息被委托类执行后的后续处理.为了保持行为的一致性,代理类和委托类通常会实现相同的接口. 按照代理的创建时期,代理类可分为两种: 静态代理:由程序员创建代理类或特定工具自动生成源代码再对其编译,也就是说在程序运行前代理类的.class文件就已经存在.动态代理:在程序运行时运用反射机制动态创建生成. 下面在将动态代理的实现机制之前先简单介绍一下静态代理. 二.

求救,java动态代理问题!

问题描述 各位同学:如何得到Java动态代理方法Proxy.newProxyInstance产生的临时代理类的内部结构是什么? 解决方案 解决方案二:你看下这个类的原码吧.解决方案三:http://www.ibm.com/developerworks/cn/java/j-lo-proxy1/index.html?ca=drs-cn-0121我当时看动态代理的时候看过这篇文章,写的很好,推荐一下

java动态代理的基础问题

问题描述 java动态代理的基础问题 import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.List; import java.util.Vector; public class VectorProxy implements InvocationHandler { private Object pro

关于java动态代理的一个奇怪问题

问题描述 在使用java动态代理时遇到一个怪异的现象,不知道正不正常:由Proxy..newProxyInstance()生成的代理对象会同时代理除了接口以外的其他方法.源码如下:public interface Talkable {public void talk();public void cry();}public class Baby implements Talkable{@Overridepublic void cry() {System.out.println("Wa!!!!!!!

详解java动态代理的2种实现方式_java

java的动态代理在接java的api上有说明,这里就不写了.我理解的代理: 对特定接口中特定方法的功能进行扩展,这就是代理.代理是通过代理实例关联的调用处理程序对象调用方法. 下面通过一个例子看一下: 接口: public interface Num { void show(); int getNum(); int getProduct(int x); } 实现类: public class MyNum implements Num { @Override public int getNum(