JDK动态代理原理详解

    xiaoxiao2025-06-16  10

    1、动态代理的概念

    动态代理即动态的代理模式,所谓动态,是指抽象类(即抽象角色)在编译期是未确定的,在运行期生成。相对的,静态代理中抽象类的行为是在编译期确定的。动态代理是 AOP(面向切面编程)常见的实现方式。

    2 、动态代理的使用示例

    public class ProxyTest { public static void main(String[] args) { System.out.println(System.getSecurityManager()); NumberOperationInterface proxied = new NumberOperationImp(); NumberOperationInterface real = wrap(proxied);//生成的是代理的对象 System.out.println(real.add(1, 2)); System.out.println(real.mutilp(2, 3)); } public static NumberOperationInterface wrap(NumberOperationInterface proxied) { return (NumberOperationInterface)Proxy.newProxyInstance(NumberOperationInterface.class.getClassLoader(), new Class[]{ NumberOperationInterface.class}, new NumberOperationImpProxyHandler(proxied)); } 被代理的对象为:proxied , proxied 实现了NumberOperationInterface 接口代理对象通过 Proxy.newProxyInstance() 函数生成的。当代理对象调用被代理对象的方法时,会调用到NumberOperationImpProxyHandler 里面的invoke 方in法。我们可以在invoke 方法实现一些功能,然后再调用method.invoke(proxied, args),就可以执行到被代理对象里面的具体方法。这就是JDK动态代理实现的基本步骤。

    问题:

    动态代理对象是如何实现。动态代理对象里面有哪些具体的方法。为什么调用被代理对象的方法时会先调用到handler 里面的invoke 方法。

    3、JDK动态代理的实现原理

    Proxy.newProxyInstance 的实现: public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException { final Class<?>[] intfs = interfaces.clone(); // 通过类加载器和接口使用 getProxyClass0 方法创建实现类,这个实现类就是代理类 Class<?> cl = getProxyClass0(loader, intfs); // 下面的代码是根据指定参数的构造器生成具体的代理类对象。 ///private static final Class<?>[] constructorParams = { InvocationHandler.class }; final Constructor<?> cons = cl.getConstructor(constructorParams); return cons.newInstance(new Object[]{h}); } //跟进Class<?> cl = getProxyClass0(loader, intfs) private static Class<?> getProxyClass0(ClassLoader loader, Class<?>... interfaces) { return proxyClassCache.get(loader, interfaces); } // 跟进proxyClassCache.get(loader, interfaces); public V get(K key, P parameter) { // Cache 置换、检查等实现均已省略,以下是 Cache 未命中时,创建新实现类的代码 Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter)); V value = supplier.get(); return value; } //跟进至 ProxyClassFactory#apply 的实现:(subKeyFactory的具体实现为ProxyClassFactory) public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) { for (Class<?> intf : interfaces) { interfaceClass = Class.forName(intf.getName(), false, loader); // 对 interfaceClass 进行了系列权限检查,实现略 } // 根据 interfaces、accessFlags 产生名为 proxyName 的代理类字节码 byte[] proxyClassFile = ProxyGenerator.generateProxyClass(proxyName, interfaces, accessFlags); // 加载字节码,产生类对象 return defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length); } // 从代码里面可以看出,先通过ProxyGenerator.generateProxy()生成代理类的字节码数组 // 再通过defineClass0()加载字节码数组生成代理类对象。

    3、动态代理类的结构

    通过ProxyGenerator.generateProxyClass("TestProxy", new Class[]{NumberOperationInterface.class}),产生一个名为TestProxy,实现NumberOperationInterface的代理类的字节码数组, FileOutputStream fileOutputStream = new FileOutputStream("TestProxy.class"); fileOutputStream.write(ProxyBytes); 通过FileOutputStream 将字节码数组写入TestProxy.class文件,生成字节码文件,接下来通过jdk-gui 字节码文件进行反编译来查看其对应的类结构如下: import dynamicProxy.jdk.NumberOperationInterface; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.lang.reflect.UndeclaredThrowableException; public final class TestProxy extends Proxy implements NumberOperationInterface { private static Method m1; private static Method m2; private static Method m3; private static Method m4; private static Method m0; public TestProxy(InvocationHandler paramInvocationHandler) throws { super(paramInvocationHandler); } public final boolean equals(Object paramObject) throws { 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 String toString() throws { try { return (String)this.h.invoke(this, m2, null); } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public final int add(int paramInt1, int paramInt2) throws { try { return ((Integer)this.h.invoke(this, m3, new Object[] { Integer.valueOf(paramInt1), Integer.valueOf(paramInt2) })).intValue(); } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public final int mutilp(int paramInt1, int paramInt2) throws { try { return ((Integer)this.h.invoke(this, m4, new Object[] { Integer.valueOf(paramInt1), Integer.valueOf(paramInt2) })).intValue(); } catch (Error|RuntimeException localError) { throw localError; } catch (Throwable localThrowable) { throw new UndeclaredThrowableException(localThrowable); } } public final int hashCode() throws { 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") }); m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]); m3 = Class.forName("dynamicProxy.jdk.NumberOperationInterface").getMethod("add", new Class[] { Integer.TYPE, Integer.TYPE }); m4 = Class.forName("dynamicProxy.jdk.NumberOperationInterface").getMethod("mutilp", new Class[] { Integer.TYPE, Integer.TYPE }); 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()); } } }

    这个代理类有5个方法,这个5个方法对应的对象m0-m4,其中m3,m4对象对应接口里面的方法。 在代理类里面接口的方法的具体实现

    public final int mutilp(int paramInt1, int paramInt2) return ((Integer)this.h.invoke(this, m4, new Object[] { Integer.valueOf(paramInt1), Integer.valueOf(paramInt2)});

    可以看到代理类在调用接口的方法时,会调用到h.invoke()方法,而h 就是之前传入的NumberOperationImpProxyHandler,到这里一切真相大白。

    4、总结

    Java 通过 Proxy.newProxyInstance 方法传入类加载器、接口类对象、调用处理器来创建代理类实例。 JDK 中通过 ProxyGenerator.generateProxyClass 方法,根据传入的接口类生成代理类的字节码,并加载字节码产生代理类,并通过反射生成代理类对象。 生成的代理类对象继承了 Proxy 实现了传入的接口类。 代理类对象每一个方法执行都会调用处理器的 invoke 方法,最后返回 invoke 方法的返回值。
    最新回复(0)