文章

动态代理(二)之JDK

本文基于 Dubbo 2.6.1 版本,望知悉。

1. 概述

本文接 《精尽 Dubbo 源码分析 —— 动态代理(一)之 Javassist》 一文,分享使用 JDK 生成动态代理的代码实现。

如果 JDK Proxy 不熟悉的胖友,可以看下 《 Java JDK 动态代理(AOP)使用及实现原理分析》 学习下。学无止境呀。

另外,如果使用 JDK 生成代理,配置方式如下:

1
2
3
4
5
// 服务引用
<dubbo:reference proxy="jdk" />

// 服务暴露
<dubbo:service proxy="jdk" />

2. JdkProxyFactory

com.alibaba.dubbo.rpc.proxy.jdk.JdkProxyFactory ,实现 AbstractProxyInvoker 抽象类,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class JdkProxyFactory extends AbstractProxyFactory {

    @SuppressWarnings("unchecked")
    public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
        return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), interfaces, new InvokerInvocationHandler(invoker));
    }

    public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
        return new AbstractProxyInvoker<T>(proxy, type, url) {
            @Override
            protected Object doInvoke(T proxy, String methodName,
                                      Class<?>[] parameterTypes,
                                      Object[] arguments) throws Throwable {
                // 获得方法
                Method method = proxy.getClass().getMethod(methodName, parameterTypes);
                // 调用方法
                return method.invoke(proxy, arguments);
            }
        };
    }

}
  • #getProxy(invoker, interfaces) 方法
    • 第 5 行:创建 InvokerInvocationHandler 对象,传入 invoker 对象。
    • 第 5 行:调用 java.lang.reflect.Proxy#getProxy(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 方法,创建 Proxy 对象。
    • 相比 Javassist 精简很多,期待 JDK Proxy 的不断性能优化。
  • #getInvoker(proxy, type, url) 方法
    • 第 9 至 19 行:创建 AbstractProxyInvoker 对象,实现 #doInvoker(…) 方法。
      • 第 15 行:调用 Class#getMethod(String name, Class<?>… parameterTypes) 方法,反射获得方法。
      • 第 17 行:调用 Method#invoke(proxy, arguments) 方法,执行方法。
      • 推荐阅读:《Java反射原理简析》

666. 彩蛋

知识星球

知识星球

推荐对动态代理的性能感兴趣的胖友,可阅读 《动态代理方案性能对比》

本文由作者按照 CC BY 4.0 进行授权