Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(), handler);
JDK的动态代理是基于实现具体实现类实现的接口来生成动态的类字节码的,生成的代理类和具体的实现类没有任何关系,代理类中保存了实现InvocationHandler接口的引用,调用某个具体的方法的时候会调用这个实现了InvocationHandler接口的invoke()方法。
动态代理的原理就是运行时生成字节码文件,试想一下我们再运行时是可以得到一个类的信息,我们就可以运行时生成这个类的代理类的java文件(通过实现目标类实现的借口或者直接继承自目标类CGLIB),并把这个java类动态编译成class文件,使用一个类加载器将当前类加载进内存,然后将这个代理类返回,与我们所描述的不同的是,动态代理是直接操纵的类的字节码文件,并没有我们所说的形成java类并编译的过程,跟踪Proxy.newProxyInstance()方法,可以看到经过一系列的验证、优化、缓存、同步生成字节码,用参数中传递的ClassLoader显示加载等动作,最终是调用到sun.misc.ProxyGenerator.generateProxyClass()方法来完成生成字节码的操作的。
以下就是JDK动态代理生成的字节码反编译后的文件内容:
package org.fenixsoft.bytecode;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
public final class $Proxy0 extends Proxy
implements DynamicProxyTest.IHello
{
private static Method m3;
private static Method m1;
private static Method m0;
private static Method m2;
public $Proxy0(InvocationHandler paramInvocationHandler)
throws
{
super(paramInvocationHandler);
}
public final void sayHello()
throws
{
try
{
this.h.invoke(this, m3, null);
return;
}
catch (RuntimeException localRuntimeException)
{
throw localRuntimeException;
}
catch (Throwable localThrowable)
{
throw new UndeclaredThrowableException(localThrowable);
}
}
// 此处由于版面原因,省略equals()、hashCode()、toString()三个方法的代码
// 这3个方法的内容与sayHello()非常相似。
static
{
try
{
m3 = Class.forName("org.fenixsoft.bytecode.DynamicProxyTest$IHello").getMethod("sayHello", new Class[0]);
m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] { Class.forName("java.lang.Object") });
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());
}
}
}