java动态代理原理解析

 DamInterface;

public interface DamInterface {

  public void sayHello();

  public int sayHelloa();

}

 DamImpl;

 public class DamImpl implements DamInterface {

  @Override
  public void sayHello() {
    System.out.println("Hello");
  }

  @Override
  public int sayHelloa() {
    System.out.println("Helloa");
    return 0;
  }

}

 DamInvocationHandler;

 public class DamInvocationHandler implements InvocationHandler {


  private Object target;

  public DamInvocationHandler(Object target) {
    super();
    this.target = target;
  }

  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    Object result = null;
    result = method.invoke(proxy, args);
    return result;
  }

  public Object getProxy() {
    return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass()
        .getInterfaces(), this);
  }
}

 ProxyMain;

 public class ProxyMain {


  public static void main(String[] args) {
    DamInterface dam = new DamImpl();
    DamInvocationHandler handler = new DamInvocationHandler(dam);
    // 创建动态代理对象
    DamInterface proxy = (DamInterface) handler.getProxy();
    proxy.sayHello();
    proxy.sayHelloa();
  }
}

 运行后返回

 Exception in thread "main" java.lang.reflect.UndeclaredThrowableException
    at com.sun.proxy.$Proxy0.sayHello(Unknown Source)
    at com.jd.o2o.proxy.ProxyMain.main(ProxyMain.java:12)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.jd.o2o.proxy.DamInvocationHandler.invoke(DamInvocationHandler.java:19)
    ... 2 more

 程序貌似进入了死循环了!!!

 采用笨办法 利用ProxyGenerator 生成代理class文件保存下来 反编译查看究竟是什么原因

  public static void main(String[] args) {
    DamInterface dam = new DamImpl();
    byte[] generateProxyClass =
        ProxyGenerator.generateProxyClass("Dam$1", dam.getClass().getInterfaces());

    try {
      File file = new File("d:/Dam$1.class");
      FileOutputStream fos = new FileOutputStream(file);
      fos.write(generateProxyClass);
      fos.close();
    } catch (Exception e) {
      e.printStackTrace();
    }

  } 

 在系统d盘根目录下生成了一个Dam$1.class文件 反编译后如下

public final class Dam$1 extends Proxy
  implements DamInterface
{
  private static Method m4;
  private static Method m1;
  private static Method m3;
  private static Method m0;
  private static Method m2;

  public final void sayHello()
    throws 
  {
    try
    {
      this.h.invoke(this, m4, null);
      return;
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final boolean equals(Object paramObject)
    throws 
  {
    try
    {
      return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final int sayHelloa()
    throws 
  {
    try
    {
      return ((Integer)this.h.invoke(this, m3, null)).intValue();
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final int hashCode()
    throws 
  {
    try
    {
      return ((Integer)this.h.invoke(this, m0, null)).intValue();
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  public final String toString()
    throws 
  {
    try
    {
      return ((String)this.h.invoke(this, m2, null));
    }
    catch (RuntimeException localRuntimeException)
    {
      throw localRuntimeException;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }

  static
  {
    try
    {
      m4 = Class.forName("com.jd.o2o.proxy.DamInterface").getMethod("sayHello", new Class[0]);
      m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
      m3 = Class.forName("com.jd.o2o.proxy.DamInterface").getMethod("sayHelloa", new Class[0]);
      m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
      return;
    }
    catch (NoSuchMethodException localNoSuchMethodException)
    {
      throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
    }
    catch (ClassNotFoundException localClassNotFoundException)
    {
      throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
    }
  }

} 

 反编译后发现Proxy后的Dam采用调用接口Proxy中的InvocationHandler的invoke方法,我们采用自己的DamInvocationHandler 故调用我们的invoke方法,此时查看代码反射调用是的Proxy的sysHello方法,故进入反射的循环调用了,所以出现了我们看到的死循环的打印错误信息

 因为我们创建的是代理对象,所以此时DamInvocationHandler 的invoke方法应该改为调用target对象,因为代理的只是接口,所以真正调用应该为调用target的实现

修改 DamInvocationHandler invoke方法为

 @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    Object result = null;
    result = method.invoke(target, args);
    return result;

  } 

 然后运行ProxyMain

posted @ 2016-05-01 17:22  6小贝  阅读(741)  评论(0编辑  收藏  举报