yy629 发表于 2013-2-3 11:37:16

java的动态代理到底生成了什么?

java的动态代理到底生成了什么?
http://yy629.iteye.com 344850459 日期: 2010-06-01

我们对java的动态代理机制可能都会使用, 但对于java生成动态生成接口的实现类可能不是很了解.
通过查看Proxy中的newProxyInstance方法, 发现最终都是由ProxyGenerator类来完成的, ProxyGenerator.generateProxyClass方法生成了实现类的字节码, 然后加载到虚拟机中的.
   那生成的字节码是什么样子的? 我们可以将生成的字节码保存到文件中, 然后反编译就可以看到它的真面目了.

package demo;import java.io.File;import java.lang.reflect.Field;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import java.util.Properties;/** * @author yeyong */public class ProxyTest2 {public static void main(String[] args) throws Exception {      // 添加以下的几段代码, 就可以将代理生成的字节码保存起来了    Field field = System.class.getDeclaredField("props");    field.setAccessible(true);    Properties props = (Properties) field.get(null);    props.put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");    Package pkg = ProxyTest2.class.getPackage();    if (pkg != null) {      String packagePath = pkg.getName().replace(".", File.pathSeparator);      new File(packagePath).mkdirs();    }    IA a = new IAImpl();    InvocationHandlerImpl ih = new InvocationHandlerImpl(a);    IA proxyA = (IA) Proxy.newProxyInstance(a.getClass().getClassLoader(),         a.getClass().getInterfaces(), ih);    proxyA.a();}}interface IA {void a();int b(String str);}class IAImpl implements IA {@Overridepublic void a() {    System.out.println("IAImpl.a()");}@Overridepublic int b(String str) {System.out.println("IAImpl.b()");    return 0;}}class InvocationHandlerImpl implements InvocationHandler {private Object target;public InvocationHandlerImpl(Object target) {    this.target = target;}public Object invoke(Object proxy, Method method, Object[] args)       throws Throwable {    System.out.println("before...");    Object res = method.invoke(target, args);    System.out.println("after...");    return res;}}
通过运行上面的代码, 我们就可以看到生成的类文件 $Proxy0.class

我们将其反编译一下, 得到它的java源码
package demo;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 IA {private static Method m1;private static Method m4;private static Method m3;private static Method m0;private static Method m2;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 (RuntimeException localRuntimeException) {      throw localRuntimeException;    } catch (Throwable localThrowable) {      throw new UndeclaredThrowableException(localThrowable);    }}public final int b(String paramString) {    try {      return ((Integer) this.h.invoke(this, m4,         new Object[] { paramString })).intValue();    } catch (RuntimeException localRuntimeException) {      throw localRuntimeException;    } catch (Throwable localThrowable) {      throw new UndeclaredThrowableException(localThrowable);    }}public final void a() {    try {      this.h.invoke(this, m3, null);      return;    } catch (RuntimeException localRuntimeException) {      throw localRuntimeException;    } catch (Throwable localThrowable) {      throw new UndeclaredThrowableException(localThrowable);    }}public final int hashCode() {    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() {    try {      return (String) this.h.invoke(this, m2, null);    } catch (RuntimeException localRuntimeException) {      throw localRuntimeException;    } catch (Throwable localThrowable) {      throw new UndeclaredThrowableException(localThrowable);    }}static {    try {      m1 = Class.forName("java.lang.Object").getMethod("equals",          new Class[] { Class.forName("java.lang.Object") });      m4 = Class.forName("demo.IA").getMethod("b",         new Class[] { Class.forName("java.lang.String") });      m3 = Class.forName("demo.IA").getMethod("a", new Class);      m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class);      m2 = Class.forName("java.lang.Object").getMethod("toString", new Class);    } catch (NoSuchMethodException localNoSuchMethodException) {      throw new NoSuchMethodError(localNoSuchMethodException.getMessage());    } catch (ClassNotFoundException localClassNotFoundException) {      throw new NoClassDefFoundError(localClassNotFoundException.getMessage());    }}}

动态生成的实现类中的所有方法都是调用了this.h.invoke方法(即InvocationHandler的接口方法).

看到此, 也明白了java动态代理的实现机制了.http://www.agoit.com/images/smiles/icon_biggrin.gif
通过Proxy.newProxyInstance`调用ProxyGenerator.generateProxyClass方法获得实现类的字节码数据, 然后加载到jvm中, 在调用构造函数, 生成实例. 这里是简化的过程, 其中还有一些权限检查,缓存和优化处理等, 对于如何生成class文件的, 可以看下ProxyGenerator的代码, 简单的说就是按照指定的格式写入字节码, 可以看出, 生成的实现类方法都是很有规律的
页: [1]
查看完整版本: java的动态代理到底生成了什么?