java.lang.reflect.Proxy类是通过创建一个新的Java类(类名为com.sun.proxy.$ProxyXXX)的方式来实现无侵入的类方法代理功能的。

    动态代理生成出来的类有如下技术细节和特性:

    1. 动态代理的必须是接口类,通过动态生成一个接口实现类来代理接口的方法调用(反射机制)。
    2. 动态代理类会由java.lang.reflect.Proxy.ProxyClassFactory创建。
    3. ProxyClassFactory会调用sun.misc.ProxyGenerator类生成该类的字节码,并调用java.lang.reflect.Proxy.defineClass0()方法将该类注册到JVM
    4. 该类继承于java.lang.reflect.Proxy并实现了需要被代理的接口类,因为java.lang.reflect.Proxy类实现了java.io.Serializable接口,所以被代理的类支持序列化/反序列化
    5. 该类实现了代理接口类(示例中的接口类是com.anbai.sec.proxy.FileSystem),会通过ProxyGenerator动态生成接口类(FileSystem)的所有方法,
    6. 该类因为实现了代理的接口类,所以当前类是代理的接口类的实例(proxyInstance instanceof FileSystemtrue),但不是代理接口类的实现类的实例(proxyInstance instanceof UnixFileSystemfalse)。
    7. 该类方法中包含了被代理的接口类的所有方法,通过调用动态代理处理类(InvocationHandler)的invoke方法获取方法执行结果。
    8. 该类代理的方式重写了java.lang.Object类的toStringhashCodeequals方法。
    9. 如果动过动态代理生成了多个动态代理类,新生成的类名中的0会自增,如com.sun.proxy.$Proxy0/$Proxy1/$Proxy2

    动态代理生成的com.sun.proxy.$Proxy0类代码:

    1. package com.sun.proxy.$Proxy0;
    2. import java.io.File;
    3. import java.lang.reflect.InvocationHandler;
    4. import java.lang.reflect.Method;
    5. import java.lang.reflect.Proxy;
    6. import java.lang.reflect.UndeclaredThrowableException;
    7. public final class $Proxy0 extends Proxy implements FileSystem {
    8. private static Method m1;
    9. // 实现的FileSystem接口方法,如果FileSystem里面有多个方法那么在这个类中将从m3开始n个成员变量
    10. private static Method m3;
    11. private static Method m0;
    12. private static Method m2;
    13. public $Proxy0(InvocationHandler var1) {
    14. super(var1);
    15. }
    16. public final boolean equals(Object var1) {
    17. try {
    18. return (Boolean) super.h.invoke(this, m1, new Object[]{var1});
    19. } catch (RuntimeException | Error var3) {
    20. throw var3;
    21. } catch (Throwable var4) {
    22. throw new UndeclaredThrowableException(var4);
    23. }
    24. }
    25. public final String[] list(File var1) {
    26. try {
    27. return (String[]) super.h.invoke(this, m3, new Object[]{var1});
    28. } catch (RuntimeException | Error var3) {
    29. throw var3;
    30. } catch (Throwable var4) {
    31. throw new UndeclaredThrowableException(var4);
    32. }
    33. }
    34. public final int hashCode() {
    35. try {
    36. return (Integer) super.h.invoke(this, m0, (Object[]) null);
    37. } catch (RuntimeException | Error var2) {
    38. throw var2;
    39. } catch (Throwable var3) {
    40. throw new UndeclaredThrowableException(var3);
    41. }
    42. }
    43. public final String toString() {
    44. try {
    45. return (String) super.h.invoke(this, m2, (Object[]) null);
    46. } catch (RuntimeException | Error var2) {
    47. throw var2;
    48. } catch (Throwable var3) {
    49. throw new UndeclaredThrowableException(var3);
    50. }
    51. }
    52. static {
    53. try {
    54. m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
    55. m3 = Class.forName("com.anbai.sec.proxy.FileSystem").getMethod("list", Class.forName("java.io.File"));
    56. m0 = Class.forName("java.lang.Object").getMethod("hashCode");
    57. m2 = Class.forName("java.lang.Object").getMethod("toString");
    58. } catch (NoSuchMethodException var2) {
    59. throw new NoSuchMethodError(var2.getMessage());
    60. } catch (ClassNotFoundException var3) {
    61. throw new NoClassDefFoundError(var3.getMessage());
    62. }
    63. }
    64. }