前言
接着上一个讲,讲到了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,它是通过继承代理类的形式,所以对代理类没有要求。