• Dubbo Invoker


    Dubbo官网对Invoker进行了说明:

    Invoker 是实体域,它是 Dubbo 的核心模型,其它模型都向它靠扰,或转换成它,它代表一个可执行体,可向它发起 invoke 调用,它有可能是一个本地的实现,也可能是一个远程的实现,也可能一个集群实现。

    在服务提供方,Invoker 用于调用服务提供类。在服务消费方,Invoker 用于执行远程调用。Invoker 是由 Protocol 实现类构建而来。

    服务提供者的Invoker的创建过程

    在服务发布ServiceConfig的export方法中,最后发布的实际上是一个经过增强的Invoker对象,下面具体分析一下Invoker的创建逻辑。

        // 通过动态代理转换成Invoker
        Invoker invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(EXPORT_KEY, url.toFullString()));
        DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
    
        // 服务发布
        Exporter exporter = protocol.export(wrapperInvoker);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    上面代码中的PROXY_FACTORY实际上是ProxyFactory的自适应扩展点:

        private static final ProxyFactory PROXY_FACTORY = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
    
    • 1

    默认是由javassist实现,每个方法都由@Adaptive注解修饰。

    因此调用getInvoker方法时,会创建一个ProxyFactory$Adaptive动态代理类。

    @SPI("javassist")
    public interface ProxyFactory {
    
        /**
         * create proxy.
         *
         * @param invoker
         * @return proxy
         */
        @Adaptive({PROXY_KEY})
         T getProxy(Invoker invoker) throws RpcException;
    
        /**
         * create proxy.
         *
         * @param invoker
         * @return proxy
         */
        @Adaptive({PROXY_KEY})
         T getProxy(Invoker invoker, boolean generic) throws RpcException;
    
        /**
         * create invoker.
         *
         * @param 
         * @param proxy
         * @param type
         * @param url
         * @return invoker
         */
        @Adaptive({PROXY_KEY})
         Invoker getInvoker(T proxy, Class type, URL url) throws RpcException;
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    ProxyFactory$Adaptive

    通过下面生成的代码可以看到,getInvoker方法会找到extName为javassist的静态扩展点,该扩展点的实现可以在SPI配置文org.apache.dubbo.rpc.ProxyFactory中得到,即:javassist=org.apache.dubbo.rpc.proxy.javassist.JavassistProxyFactory

    public class ProxyFactory$Adaptive implements org.apache.dubbo.rpc.ProxyFactory {
        public java.lang.Object getProxy(org.apache.dubbo.rpc.Invoker arg0) throws org.apache.dubbo.rpc.RpcException {
            if (arg0 == null)
                throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument == null");
            if (arg0.getUrl() == null)
                throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument getUrl() == null");
            org.apache.dubbo.common.URL url = arg0.getUrl();
            String extName = url.getParameter("proxy", "javassist");
            if (extName == null)
                throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.ProxyFactory) name from url (" + url.toString()
                        + ") use keys([proxy])");
            org.apache.dubbo.rpc.ProxyFactory extension =
                    (org.apache.dubbo.rpc.ProxyFactory) ExtensionLoader.getExtensionLoader(org.apache
                            .dubbo.rpc.ProxyFactory.class).getExtension(extName);
            return extension.getProxy(arg0);
        }
    
        public java.lang.Object getProxy(org.apache.dubbo.rpc.Invoker arg0, boolean arg1) throws org.apache.dubbo.rpc.RpcException {
            if (arg0 == null)
                throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument == null");
            if (arg0.getUrl() == null)
                throw new IllegalArgumentException("org.apache.dubbo.rpc.Invoker argument getUrl() == null");
            org.apache.dubbo.common.URL url = arg0.getUrl();
            String extName = url.getParameter("proxy", "javassist");
            if (extName == null)
                throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.ProxyFactory) name from url (" + url.toString()
                        + ") use keys([proxy])");
            org.apache.dubbo.rpc.ProxyFactory extension =
                    (org.apache.dubbo.rpc.ProxyFactory) ExtensionLoader.getExtensionLoader(org.apache
                            .dubbo.rpc.ProxyFactory.class).getExtension(extName);
            return extension.getProxy(arg0, arg1);
        }
    
        public org.apache.dubbo.rpc.Invoker getInvoker(java.lang.Object arg0, java.lang.Class arg1, org.apache.dubbo.common.URL arg2) throws org.apache.dubbo.rpc.RpcException {
            if (arg2 == null)
                throw new IllegalArgumentException("url == null");
            org.apache.dubbo.common.URL url = arg2;
            String extName = url.getParameter("proxy", "javassist");
            if (extName == null)
                throw new IllegalStateException("Failed to get extension (org.apache.dubbo.rpc.ProxyFactory) name from url (" + url.toString()
                        + ") use keys([proxy])");
            org.apache.dubbo.rpc.ProxyFactory extension =
                    (org.apache.dubbo.rpc.ProxyFactory) ExtensionLoader.getExtensionLoader(org.apache
                            .dubbo.rpc.ProxyFactory.class).getExtension(extName);
            return extension.getInvoker(arg0, arg1, arg2);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    JavassistProxyFactory.getInvoker

    javassist是一个动态生成代码的类库,用来实现动态代理。

    proxy:目标接口的真实实现

    type:目标接口

    url:协议地址

    JavassistProxyFactory 创建了一个继承自 AbstractProxyInvoker 类的匿名对象,并覆写了抽象方法 doInvoke。覆写后的 doInvoke 逻辑比较简单,仅是将调用请求转发给了 Wrapper 类的 invokeMethod 方法。Wrapper 用于“包裹”目标类,最终还是会通过invokeMethod方法反射调用目标方法。

        @Override
        public  Invoker getInvoker(T proxy, Class type, URL url) {
            // TODO Wrapper cannot handle this scenario correctly: the classname contains '$'
            final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type);
            return new AbstractProxyInvoker(proxy, type, url) {
                @Override
                protected Object doInvoke(T proxy, String methodName,
                                          Class[] parameterTypes,
                                          Object[] arguments) throws Throwable {
                    return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
                }
            };
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 相关阅读:
    Open AI ChatGPT Prompt 学习之基础篇
    算法day30
    【C++】Floyd多源最短路算法
    多维时序 | MATLAB实现SSA-CNN-GRU-Attention多变量时间序列预测(SE注意力机制)
    2022前端CSS经典面试题
    【pandas小技巧】--列值的映射
    实验八 数据处理与多项式处理(matlab)
    CTFshow web55
    Linux免交互
    [算法周训 3] 字符串训练2
  • 原文地址:https://blog.csdn.net/m0_61083409/article/details/126716874