动态代理讲解(二)

前言

  接着上一个讲,讲到了jdk动态代理,他实际上是通过生成代理类来间接调用被代理的方法,所以要求被代理类实现接口,比较局限,是不是还是对jdk原理比较模糊,我们可以试着去解读一下源码,
我们通过 Proxy.newProxyInstance(WorkImpl.class.getClassLoader(),WorkImpl.class.getInterfaces(), handle); 来获取代理类,然后调用代理类的方法从而调用目标对象,那么在这个方法中到底做了什么呢?

  你们可以点进去看一下,总结起来就是各种合规检测.........巴拉巴拉之类的,最重要的是下面这几句

            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, interfaces, accessFlags);
            try {
                return defineClass0(loader, proxyName,
                                    proxyClassFile, 0, proxyClassFile.length);
            } catch (ClassFormatError e) {
                /*
                 * A ClassFormatError here means that (barring bugs in the
                 * proxy class generation code) there was some other
                 * invalid aspect of the arguments supplied to the proxy
                 * class creation (such as virtual machine limitations
                 * exceeded).
                 */
                throw new IllegalArgumentException(e.toString());
            }

  通过ProxyGenerator.generateProxyClass去生成代理类的二进制流,然后defineClass0转化为.class文件。
我们可以直接输出这个字节流文件看看,这样就非常清楚了

        byte[] classFile =  ProxyGenerator.generateProxyClass("$Proxy0",WorkImpl.class.getInterfaces());
        String path = "D:/$Proxy0.class";
        FileOutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(path);
            outputStream.write(classFile);
            outputStream.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                outputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

  我们打开$Proxy0.class就会发现世界都变得开朗了.

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import proxy.Work;

public final class $Proxy0
  extends Proxy
  implements Work
{
  private static Method m1;
  private static Method m3;
  private static Method m2;
  private static Method m4;
  private static Method m0;
  
  public $Proxy0(InvocationHandler paramInvocationHandler)
  {
    super(paramInvocationHandler);
  }
  
  public final boolean equals(Object paramObject)
  {
    try
    {
      return ((Boolean)this.h.invoke(this, m1, new Object[] { paramObject })).booleanValue();
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
  
  public final void doOther()
  {
    try
    {
      this.h.invoke(this, m3, null);
      return;
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
  
  public final String toString()
  {
    try
    {
      return (String)this.h.invoke(this, m2, null);
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
  
  public final void dowork()
  {
    try
    {
      this.h.invoke(this, m4, null);
      return;
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
  
  public final int hashCode()
  {
    try
    {
      return ((Integer)this.h.invoke(this, m0, null)).intValue();
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
  }
  
  static
  {
    try
    {
      m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
      m3 = Class.forName("proxy.Work").getMethod("doOther", new Class[0]);
      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);
      m4 = Class.forName("proxy.Work").getMethod("dowork", new Class[0]);
      m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);
      return;
    }
    catch (NoSuchMethodException localNoSuchMethodException)
    {
      throw new NoSuchMethodError(localNoSuchMethodException.getMessage());
    }
    catch (ClassNotFoundException localClassNotFoundException)
    {
      throw new NoClassDefFoundError(localClassNotFoundException.getMessage());
    }
  }
}

  它实际上就是给给每个接口做了代理,例如你调用work方法后,它就会去调用InvocationHandler的invoke,这样是不是就非常清楚了。
  所以这里你也应该清楚被代理的类必须实现接口吧。

  是不是感觉不太灵活,是的。在下一篇中我们将讲解另一种动态代理策略——cglib,它是通过继承代理类的形式,所以对代理类没有要求。

你可能感兴趣的:(动态代理讲解(二))