Dubbo源码解析-动态代理JDK篇

前言:

    有关于动态代理,是一个长盛不衰的话题。无论是面试还是各个框架的应用,都是热点话题。

    而关于Dubbo的动态代理,有两种实现方式:一种是JDK,另一种是Javassist。

    本文来介绍下JDK动态代理的使用方式,并简单分析下其源码实现。

1.JDK动态打理示例

1.1 创建接口及实现类

// 接口
public interface Subject {
    String say(String name);
}

// 实现类
public class RealSubject implements Subject {
    @Override
    public String say(String name) {
        return "hello " + name;
    }
}

1.2 创建动态代理及测试

public static void main(String[] args) {
    Subject realSubject = new RealSubject();
    
    // 通过Proxy.newProxyInstance来创建
    Subject subject = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), new InvocationHandler() {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        	// 在真正调用realSubject 方法的前后,执行自定义方法
            System.out.println("before invoke...");
            Object res = method.invoke(realSubject, args);
            System.out.println("after invoke...");
            return res;
        }
    });

    String hello = subject.say("jack");
    System.out.println(hello);
}

// 结果:
before invoke...
after invoke...
hello jack

通过一个简单的示例,了解下JDK的动态代理Proxy的使用。

那么Proxy.newProxyInstance()方法返回的究竟是什么呢?进入方法源码后可以看到返回的是Object,我们还可以通过类型强转将Object转换为我们的接口类型Subject,那么说明这个Object应该是Subject的实现类。如何验证呢?

2.分析Proxy.newProxyInstance()返回值

    我们在这个方法进行debug,可以看到,最终返回的是$Proxy0对象,这个是动态生成的类。我们可以通过HSDB来查看这个类的具体内容

2.1 $Proxy0具体内容

    以下代码进行了format,通过反编译工具出来的代码格式有点乱。

package com.sun.proxy;
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 Subject {
    private static Method m1;
    private static Method m2;
    private static Method m3;
    private static Method m0;

    public $Proxy0(InvocationHandler paramInvocationHandler) {
        super(paramInvocationHandler);
    }

    static {
        try {
            // 分别对应Object的一些基本方法和我们代理的接口的方法
            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("xw.demo.proxy.Subject").getMethod("say", new Class[]{Class.forName("java.lang.String")});
            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());
        }
    }

    public final boolean equals(Object paramObject) {
        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() {
        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 hashCode() {
        try {
            return ((Integer) this.h.invoke(this, m0, null)).intValue();
        } catch (Error | RuntimeException localError) {
            throw localError;
        } catch (Throwable localThrowable) {
            throw new UndeclaredThrowableException(localThrowable);
        }
    }

// 重点在这里
    public final String say(String paramString) {
        try {
            // 通过调用h.invoke()方法来实现
            // m3即xw.demo.proxy.Subject接口的say()方法对应的Method对象
            return (String) this.h.invoke(this, m3, new Object[]{paramString});
        } catch (Error | RuntimeException localError) {
            throw localError;
        } catch (Throwable localThrowable) {
            throw new UndeclaredThrowableException(localThrowable);
        }
    }
}

通过生成类$Proxy0的查看,其实现了Subject接口,并继承了Proxy对象。

那么这个h是什么呢?就是我们在测试代码中创建的InvocationHandler接口。

通过$Proxy0的构造方法

public $Proxy0(InvocationHandler paramInvocationHandler) {
    // 调用了父类的方法
    super(paramInvocationHandler);
}

public class Proxy implements java.io.Serializable {
    protected InvocationHandler h;
    protected Proxy(InvocationHandler h) {
        Objects.requireNonNull(h);
        this.h = h;
    }
}

2.2 $Proxy0.say()

    通过对生成代码的分析,由于$Proxy0实现了Subject接口,故其可以强转为Subject。

    而$Proxy0.say()的调用本质上 还是调用了我们实现的InvocationHandler.invoke()方法

this.h.invoke(this, m3, new Object[]{paramString})

    而我们自定义的InvocationHandler.say()

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    // 在真正调用realSubject 方法的前后,执行自定义方法
    System.out.println("before invoke...");
    Object res = method.invoke(realSubject, args);
    System.out.println("after invoke...");
    return res;
}

    最终调用到被代理对象realSubject。

这样就完成了对代理对象的调用,并实现了自己的新增功能。

2.3 Proxy.newProxyInstance()源码分析

    最后,我们来看下,这个神奇的$Proxy0是如何生成的

public class Proxy implements java.io.Serializable {
 
     /**
     * a cache of proxy classes
     */
    private static final WeakCache<ClassLoader, Class<?>[], Class<?>>
        proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());
    
    protected InvocationHandler h;
    
    public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        Objects.requireNonNull(h);

        final Class<?>[] intfs = interfaces.clone();
        ...

        // 重点在这里
        Class<?> cl = getProxyClass0(loader, intfs);
        try {
            if (sm != null) {
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }

            final Constructor<?> cons = cl.getConstructor(constructorParams);
            final InvocationHandler ih = h;
            ...
            return cons.newInstance(new Object[]{h});
        } ...
    }
}

2.3.1 Proxy.getProxyClass0()

public class Proxy implements java.io.Serializable {
 
        private static Class<?> getProxyClass0(ClassLoader loader,
                                           Class<?>... interfaces) {
        if (interfaces.length > 65535) {
            throw new IllegalArgumentException("interface limit exceeded");
        }

        // If the proxy class defined by the given loader implementing
        // the given interfaces exists, this will simply return the cached copy;
        // otherwise, it will create the proxy class via the ProxyClassFactory
        return proxyClassCache.get(loader, interfaces);
    }
}

英文注释已经很明确了,proxyClassCache就是一个proxy的缓存池,如果缓存池中已经存在该接口的Proxy对象,则直接返回;否则通过ProxyClassFactory创建一个。

2.3.2 WeakCache.get()

final class WeakCache<K, P, V> {
    // 重要属性,通过构造方法传送过来的
    // 而在Proxy对象中,subKeyFactory和valueKeyFactory通过 
    // proxyClassCache = new WeakCache<>(new KeyFactory(), new ProxyClassFactory());来设置的
    
    private final BiFunction<K, P, ?> subKeyFactory;
    private final BiFunction<K, P, V> valueFactory;

    public WeakCache(BiFunction<K, P, ?> subKeyFactory,
                     BiFunction<K, P, V> valueFactory) {
        this.subKeyFactory = Objects.requireNonNull(subKeyFactory);
        this.valueFactory = Objects.requireNonNull(valueFactory);
    }


	public V get(K key, P parameter) {
        Objects.requireNonNull(parameter);

        expungeStaleEntries();

        ...
        // 关键点在这里 subKeyFactory.apply(key, parameter)
        // 这里的subKeyFactory 即Proxy.KeyFactory,其apply方法具体内容见2.3.2.1
        Object subKey = Objects.requireNonNull(subKeyFactory.apply(key, parameter));
        Supplier<V> supplier = valuesMap.get(subKey);
        Factory factory = null;

        while (true) {
            // 初始时supplier为空
            if (supplier != null) {
                // 最终调用到WeakCache.Factory.get()方法,具体见2.3.2.2
                V value = supplier.get();
                if (value != null) {
                    return value;
                }
            }
            if (factory == null) {
                // 这里的Factory
                factory = new Factory(key, parameter, subKey, valuesMap);
            }

            if (supplier == null) {
                // 将subKey和Factory组装成supplier
                // 然后再通过循环,调用到上面supplier.get()
                
                supplier = valuesMap.putIfAbsent(subKey, factory);
                if (supplier == null) {
                    supplier = factory;
                }
            } else {
                if (valuesMap.replace(subKey, supplier, factory)) {
                    // successfully replaced
                    // cleared CacheEntry / unsuccessful Factory
                    // with our Factory
                    supplier = factory;
                } else {
                    // retry with current supplier
                    supplier = valuesMap.get(subKey);
                }
            }
        }
    }
}

2.3.2.1 WeakCache.KeyFactory

    private static final class KeyFactory
        implements BiFunction<ClassLoader, Class<?>[], Object>
    {
        @Override
        public Object apply(ClassLoader classLoader, Class<?>[] interfaces) {
            switch (interfaces.length) {
                    // 本例中就继承一个接口,所以直接返回Key1对象
                case 1: return new Key1(interfaces[0]); // the most frequent
                case 2: return new Key2(interfaces[0], interfaces[1]);
                case 0: return key0;
                default: return new KeyX(interfaces);
            }
        }
    }

2.3.2.2 WeakCache.Factory

private final class Factory implements Supplier<V> {

        private final K key;
        private final P parameter;
        private final Object subKey;
        private final ConcurrentMap<Object, Supplier<V>> valuesMap;

        Factory(K key, P parameter, Object subKey,
                ConcurrentMap<Object, Supplier<V>> valuesMap) {
            this.key = key;
            this.parameter = parameter;
            this.subKey = subKey;
            this.valuesMap = valuesMap;
        }

        @Override
        public synchronized V get() { // serialize access
            Supplier<V> supplier = valuesMap.get(subKey);
            if (supplier != this) {
                return null;
            }
            V value = null;
            try {
                // 最终在这里,通过valueFactory.apply()来创建值
                // valueFactory本质上就是ProxyClassFactory
                value = Objects.requireNonNull(valueFactory.apply(key, parameter));
            } finally {
                if (value == null) { // remove us on failure
                    valuesMap.remove(subKey, this);
                }
            }
            ...
            return value;
        }
    }

2.3.2.3 ProxyClassFactory.apply()

private static final class ProxyClassFactory
        implements BiFunction<ClassLoader, Class<?>[], Class<?>>
    {
        // prefix for all proxy class names
        private static final String proxyClassNamePrefix = "$Proxy";

        // next number to use for generation of unique proxy class names
        private static final AtomicLong nextUniqueNumber = new AtomicLong();

        @Override
        public Class<?> apply(ClassLoader loader, Class<?>[] interfaces) {

            Map<Class<?>, Boolean> interfaceSet = new IdentityHashMap<>(interfaces.length);
            for (Class<?> intf : interfaces) {
                Class<?> interfaceClass = null;
                try {
                    // 这里的interface,即我们在Proxy.newProxyInstance()中传入的接口
                    interfaceClass = Class.forName(intf.getName(), false, loader);
                } catch (ClassNotFoundException e) {
                }
               ...
            }

            String proxyPkg = null;     // package to define proxy class in
            int accessFlags = Modifier.PUBLIC | Modifier.FINAL;

            for (Class<?> intf : interfaces) {
                int flags = intf.getModifiers();
                if (!Modifier.isPublic(flags)) {
                    accessFlags = Modifier.FINAL;
                    String name = intf.getName();
                    int n = name.lastIndexOf('.');
                    String pkg = ((n == -1) ? "" : name.substring(0, n + 1));
                    if (proxyPkg == null) {
                        proxyPkg = pkg;
                    } else if (!pkg.equals(proxyPkg)) {
                        throw new IllegalArgumentException(
                            "non-public interfaces from different packages");
                    }
                }
            }

            // 生成包名 com.sun.proxy.
            if (proxyPkg == null) {
                proxyPkg = ReflectUtil.PROXY_PACKAGE + ".";
            }

            // 生成proxy类名  com.sun.proxy.$Proxy0
            long num = nextUniqueNumber.getAndIncrement();
            String proxyName = proxyPkg + proxyClassNamePrefix + num;

            // 最终通过ProxyGenerator.generateProxyClass生成proxy类文件
            byte[] proxyClassFile = ProxyGenerator.generateProxyClass(
                proxyName, interfaces, accessFlags);
            try {
                // 生成一个可用类
                return defineClass0(loader, proxyName,
                                    proxyClassFile, 0, proxyClassFile.length);
            } catch (ClassFormatError e) {
                throw new IllegalArgumentException(e.toString());
            }
        }
    }

绕了这么一大圈,我们看到最终的结果了,就是通过ProxyGenerator.generateProxyClass()方法来生成对应接口的Proxy类信息。具体内容就是我们在2.1中展示的。

那么我们自定义的InvocationHandler是如何被塞入到这个$Proxy0中的呢?

让我们回到Proxy.newProxyInstance()方法中

public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
        throws IllegalArgumentException
    {
        Objects.requireNonNull(h);

        final Class<?>[] intfs = interfaces.clone();
        final SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            checkProxyAccess(Reflection.getCallerClass(), loader, intfs);
        }

        /*
         * Look up or generate the designated proxy class.
         */
        Class<?> cl = getProxyClass0(loader, intfs);

        /*
         * Invoke its constructor with the designated invocation handler.
         */
        try {
            if (sm != null) {
                checkNewProxyPermission(Reflection.getCallerClass(), cl);
            }

            // 获取$Proxy0的构造方法,入参只有一个InvocationHandler的构造方法
            final Constructor<?> cons = cl.getConstructor(constructorParams);
            ...
            // 通过构造方法将我们自定义的InvocationHandler传入,构造出$Proxy0对象
            return cons.newInstance(new Object[]{h});
        } ...
    }

总结:

    本来以为很简单的Proxy,没想到有这么多东西要写。

    针对动态代理,基本都是一样的套路,生成新的字节码类,并实例化。

猜你喜欢

转载自blog.csdn.net/qq_26323323/article/details/121468937