JDK动态代理深入解析

一、首先动态代理区别与静态代理(关于代理模式,这里不做说明,有大量的博文在讲这个概念),是程序在运行过程中创建目标接口的代理实现类。

二、下面先看一段简单的代码:

Map map = (Map) Proxy.newProxyInstance(TestProxy.class.getClassLoader(), new Class[]{Map.class}, (proxy, method, args1) -> {
    if (method.getName() == "get") {
        return "world";
    } else {
        System.out.println("不支持该方法调用");
        return null;
    }
});

System.out.println("hello  " + map.get("hello"));
map.put("a", "b");

这一段代码就创建了一个Map接口的动态代理类的实例,并调用了map的get和put方法。控制台输出如下:

这里发现一个奇怪的现象,我们并没有map接口的实现类,却得到了map对象,并调用了map接口的两个方法。

Java最基本的规则告诉我们,对象一定是一个实现类的实例,不可能直接创建一个接口的实例(即使是使用匿名内部类,也符合这条规则)。由这一点出发,我们可以判断Proxy类的newProxyInstance方法内部一定创建了一个Map接口的实现类,并被ClassLoader加载到了JVM,最后还创建了这个实现类的实例。下面对jdk源码的跟踪证实了这一设想:

1.创建Map接口的实现类。

追踪到Proxy.java 的第535行,可以发现jdk动态生成了Map接口的实现类,并加载到了JVM。

 进一步从Proxy.java的538行追踪到ProxyGenerator类的第527行,会看到class类文件头的魔法数 CAFFBABE(这个魔法数还有个浪漫的故事),说明JDK确实在创建一个Map接口的实现类。

 

在调试Proxy.java第538行的时候执行如下代码,可以将JDK生成的类输出到proxy.class文件:

new FileOutputStream("/Users/XXX/Downloads/tt/proxy.class").write(proxyClassFile)

生成的calss文件反编译后结果如下:


package com.sun.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;

public final class $Proxy0 extends Proxy implements Map {
    private static Method m1;
    private static Method m21;
    private static Method m5;
    private static Method m3;
    private static Method m4;
    private static Method m22;
    private static Method m0;
    private static Method m7;
    private static Method m16;
    private static Method m24;
    private static Method m8;
    private static Method m17;
    private static Method m9;
    private static Method m20;
    private static Method m2;
    private static Method m14;
    private static Method m23;
    private static Method m19;
    private static Method m25;
    private static Method m6;
    private static Method m10;
    private static Method m11;
    private static Method m12;
    private static Method m18;
    private static Method m15;
    private static Method m13;

    public $Proxy0(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final Object computeIfAbsent(Object var1, Function var2) throws  {
        try {
            return (Object)super.h.invoke(this, m21, new Object[]{var1, var2});
        } catch (RuntimeException | Error var4) {
            throw var4;
        } catch (Throwable var5) {
            throw new UndeclaredThrowableException(var5);
        }
    }

    public final Object get(Object var1) throws  {
        try {
            return (Object)super.h.invoke(this, m5, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final Object remove(Object var1) throws  {
        try {
            return (Object)super.h.invoke(this, m3, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final boolean remove(Object var1, Object var2) throws  {
        try {
            return (Boolean)super.h.invoke(this, m4, new Object[]{var1, var2});
        } catch (RuntimeException | Error var4) {
            throw var4;
        } catch (Throwable var5) {
            throw new UndeclaredThrowableException(var5);
        }
    }

    public final boolean containsValue(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m22, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final Collection values() throws  {
        try {
            return (Collection)super.h.invoke(this, m7, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void putAll(Map var1) throws  {
        try {
            super.h.invoke(this, m16, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final Object getOrDefault(Object var1, Object var2) throws  {
        try {
            return (Object)super.h.invoke(this, m24, new Object[]{var1, var2});
        } catch (RuntimeException | Error var4) {
            throw var4;
        } catch (Throwable var5) {
            throw new UndeclaredThrowableException(var5);
        }
    }

    public final void clear() throws  {
        try {
            super.h.invoke(this, m8, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final Object putIfAbsent(Object var1, Object var2) throws  {
        try {
            return (Object)super.h.invoke(this, m17, new Object[]{var1, var2});
        } catch (RuntimeException | Error var4) {
            throw var4;
        } catch (Throwable var5) {
            throw new UndeclaredThrowableException(var5);
        }
    }

    public final boolean isEmpty() throws  {
        try {
            return (Boolean)super.h.invoke(this, m9, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final boolean containsKey(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m20, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final Object merge(Object var1, Object var2, BiFunction var3) throws  {
        try {
            return (Object)super.h.invoke(this, m14, new Object[]{var1, var2, var3});
        } catch (RuntimeException | Error var5) {
            throw var5;
        } catch (Throwable var6) {
            throw new UndeclaredThrowableException(var6);
        }
    }

    public final Set keySet() throws  {
        try {
            return (Set)super.h.invoke(this, m23, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final void forEach(BiConsumer var1) throws  {
        try {
            super.h.invoke(this, m19, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final Object computeIfPresent(Object var1, BiFunction var2) throws  {
        try {
            return (Object)super.h.invoke(this, m25, new Object[]{var1, var2});
        } catch (RuntimeException | Error var4) {
            throw var4;
        } catch (Throwable var5) {
            throw new UndeclaredThrowableException(var5);
        }
    }

    public final Object put(Object var1, Object var2) throws  {
        try {
            return (Object)super.h.invoke(this, m6, new Object[]{var1, var2});
        } catch (RuntimeException | Error var4) {
            throw var4;
        } catch (Throwable var5) {
            throw new UndeclaredThrowableException(var5);
        }
    }

    public final Object replace(Object var1, Object var2) throws  {
        try {
            return (Object)super.h.invoke(this, m10, new Object[]{var1, var2});
        } catch (RuntimeException | Error var4) {
            throw var4;
        } catch (Throwable var5) {
            throw new UndeclaredThrowableException(var5);
        }
    }

    public final boolean replace(Object var1, Object var2, Object var3) throws  {
        try {
            return (Boolean)super.h.invoke(this, m11, new Object[]{var1, var2, var3});
        } catch (RuntimeException | Error var5) {
            throw var5;
        } catch (Throwable var6) {
            throw new UndeclaredThrowableException(var6);
        }
    }

    public final void replaceAll(BiFunction var1) throws  {
        try {
            super.h.invoke(this, m12, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final Object compute(Object var1, BiFunction var2) throws  {
        try {
            return (Object)super.h.invoke(this, m18, new Object[]{var1, var2});
        } catch (RuntimeException | Error var4) {
            throw var4;
        } catch (Throwable var5) {
            throw new UndeclaredThrowableException(var5);
        }
    }

    public final Set entrySet() throws  {
        try {
            return (Set)super.h.invoke(this, m15, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int size() throws  {
        try {
            return (Integer)super.h.invoke(this, m13, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m21 = Class.forName("java.util.Map").getMethod("computeIfAbsent", Class.forName("java.lang.Object"), Class.forName("java.util.function.Function"));
            m5 = Class.forName("java.util.Map").getMethod("get", Class.forName("java.lang.Object"));
            m3 = Class.forName("java.util.Map").getMethod("remove", Class.forName("java.lang.Object"));
            m4 = Class.forName("java.util.Map").getMethod("remove", Class.forName("java.lang.Object"), Class.forName("java.lang.Object"));
            m22 = Class.forName("java.util.Map").getMethod("containsValue", Class.forName("java.lang.Object"));
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
            m7 = Class.forName("java.util.Map").getMethod("values");
            m16 = Class.forName("java.util.Map").getMethod("putAll", Class.forName("java.util.Map"));
            m24 = Class.forName("java.util.Map").getMethod("getOrDefault", Class.forName("java.lang.Object"), Class.forName("java.lang.Object"));
            m8 = Class.forName("java.util.Map").getMethod("clear");
            m17 = Class.forName("java.util.Map").getMethod("putIfAbsent", Class.forName("java.lang.Object"), Class.forName("java.lang.Object"));
            m9 = Class.forName("java.util.Map").getMethod("isEmpty");
            m20 = Class.forName("java.util.Map").getMethod("containsKey", Class.forName("java.lang.Object"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m14 = Class.forName("java.util.Map").getMethod("merge", Class.forName("java.lang.Object"), Class.forName("java.lang.Object"), Class.forName("java.util.function.BiFunction"));
            m23 = Class.forName("java.util.Map").getMethod("keySet");
            m19 = Class.forName("java.util.Map").getMethod("forEach", Class.forName("java.util.function.BiConsumer"));
            m25 = Class.forName("java.util.Map").getMethod("computeIfPresent", Class.forName("java.lang.Object"), Class.forName("java.util.function.BiFunction"));
            m6 = Class.forName("java.util.Map").getMethod("put", Class.forName("java.lang.Object"), Class.forName("java.lang.Object"));
            m10 = Class.forName("java.util.Map").getMethod("replace", Class.forName("java.lang.Object"), Class.forName("java.lang.Object"));
            m11 = Class.forName("java.util.Map").getMethod("replace", Class.forName("java.lang.Object"), Class.forName("java.lang.Object"), Class.forName("java.lang.Object"));
            m12 = Class.forName("java.util.Map").getMethod("replaceAll", Class.forName("java.util.function.BiFunction"));
            m18 = Class.forName("java.util.Map").getMethod("compute", Class.forName("java.lang.Object"), Class.forName("java.util.function.BiFunction"));
            m15 = Class.forName("java.util.Map").getMethod("entrySet");
            m13 = Class.forName("java.util.Map").getMethod("size");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

以上代码就是典型的代理模式了。2.创建动态代理类的实例

Proxy.java的第1022行,使用动态代理类的构造器创建实例

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值