Dubbo服务服务暴露之ProxyFactory Invoker
2019独角兽企业重金招聘Python工程师标准>>>
Dubbo服务暴露过程中有涉及到调用ProxyFactory 中方法获取Invoker对象的过程,现在我们来深究下源码,来看下这个过程是在做些什么,返回的Invoker 对象是什么,我们来看一下代码的切入点:
Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);
这里proxyFactory实在ServiceConfig中定义的静态常量,赋值后无法修改:
private static final ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
proxyFactory通过ExtensionLoader拓展机制进行加载。查看ProxyFactory接口源码如下:
/** Copyright 1999-2011 Alibaba Group.* * Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at* * http://www.apache.org/licenses/LICENSE-2.0* * Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
package com.alibaba.dubbo.rpc;import com.alibaba.dubbo.common.Constants;
import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.extension.Adaptive;
import com.alibaba.dubbo.common.extension.SPI;/*** ProxyFactory. (API/SPI, Singleton, ThreadSafe)** @author william.liangf*/
@SPI("javassist")
public interface ProxyFactory {/*** create proxy.** @param invoker* @return proxy*/@Adaptive({Constants.PROXY_KEY})<T> T getProxy(Invoker<T> invoker) throws RpcException;/*** create invoker.** @param <T>* @param proxy* @param type* @param url* @return invoker*/@Adaptive({Constants.PROXY_KEY})<T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException;}
ProxyFactory接口有三个实现类,分别为JavassistProxyFactory、JdkProxyFactory、StubProxyFactoryWrapper。其中JavassistProxyFactory、JdkProxyFactory作为代理工厂,StubProxyFactoryWrapper实现了对代理工厂进行装饰的功能。在Dubbo中通过SPI配置默认的代理工厂为JavassistProxyFactory
接下来我们重点来看JavassistProxyFactory 代理工厂:
继承图如下:
JavassistProxyFactory 源码非常简单,只有两个方法:(代码调试的入参已经注释在源码中)
/** Copyright 1999-2011 Alibaba Group.* * Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at* * http://www.apache.org/licenses/LICENSE-2.0* * Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
package com.alibaba.dubbo.rpc.proxy.javassist;import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.bytecode.Proxy;
import com.alibaba.dubbo.common.bytecode.Wrapper;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.proxy.AbstractProxyFactory;
import com.alibaba.dubbo.rpc.proxy.AbstractProxyInvoker;
import com.alibaba.dubbo.rpc.proxy.InvokerInvocationHandler;/*** JavaassistRpcProxyFactory** @author william.liangf*/
public class JavassistProxyFactory extends AbstractProxyFactory {@SuppressWarnings("unchecked")public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));}/**** @param proxy DemoServiceImpl* @param type interface com.alibaba.dubbo.demo.DemoService* @param url injvm://127.0.0.1/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&default.accepts=1000&default.threadpool=fixed&default.threads=100&default.timeout=5000&dubbo=2.0.0&generic=false&interface=com.alibaba.dubbo.demo.DemoService&methods=sayHello&owner=uce&pid=9176&side=provider×tamp=1527927801444* @param <T>* @return*/public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {// TODO Wrapper类不能正确处理带$的类名final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass().getName().indexOf('$') < 0 ? proxy.getClass() : type);return new AbstractProxyInvoker<T>(proxy, type, url) {@Overrideprotected Object doInvoke(T proxy, String methodName,Class<?>[] parameterTypes,Object[] arguments) throws Throwable {return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);}};}}
其中getProxy是实现抽象类AbstractProxyFactory中的抽象方法。AbstractProxyFactory抽象类实现了ProxyFactory接口中getProxy方法,JdkProxyFactory也实现了抽象类AbstractProxyFactory中的getProxy抽象方法。Javassist与Jdk动态代理的共同部分被封装在父类AbstractProxyFactory中,具体的实现类只需负责实现代理生成过程的差异化部分。
其中getInvoker方法是在ProxyFactory接口中定义的,用于创建Invoker。getInvoker中代码很简单,直接返回一个匿名类。匿名类继承了AbstractProxyInvoker抽象类,AbstractProxyInvoker抽象类又实现了Invoker接口,即表明该匿名类实现了Invoker接口,匿名类是封装了服务提供者的调用者。
Invoker接口定义了一个泛型。定义的方法很简单,只有两个方法,如下:
package com.alibaba.dubbo.rpc;import com.alibaba.dubbo.common.Node;public interface Invoker<T> extends Node {//获取服务对象接口Class<T> getInterface();//获取封装了服务的调用者Result invoke(Invocation invocation) throws RpcException;}
抽象类AbstractProxyInvoker实现了Invoker接口,AbstractProxyInvoker定义属性和构造方法如下:
private final T proxy;private final Class<T> type;private final URL url;public AbstractProxyInvoker(T proxy, Class<T> type, URL url) {if (proxy == null) {throw new IllegalArgumentException("proxy == null");}if (type == null) {throw new IllegalArgumentException("interface == null");}if (!type.isInstance(proxy)) {throw new IllegalArgumentException(proxy.getClass().getName() + " not implement interface " + type);}this.proxy = proxy;this.type = type;this.url = url;}
- proxy:是final类型变量,指向服务提供者
- type:是final类型变量,服务的接口类型
- url:是final类型变量,携带服务地址、端口等多种信息的自定义URL对象
AbstractProxyInvoker也实现了invoker方法。方法内部很简单,直接通过RpcResult创建一个对象即可,创建RpcResult时的构建参数是通过方法doInvoke生成的。如下:
public Result invoke(Invocation invocation) throws RpcException {try {return new RpcResult(doInvoke(proxy, invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments()));} catch (InvocationTargetException e) {return new RpcResult(e.getTargetException());} catch (Throwable e) {throw new RpcException("Failed to invoke remote proxy method " + invocation.getMethodName() + " to " + getUrl() + ", cause: " + e.getMessage(), e);}}
这里的doInvoke方法是抽象方法,由子类实现。抽象方法定义如下:
protected abstract Object doInvoke(T proxy, String methodName, Class<?>[] parameterTypes, Object[] arguments) throws Throwable;
在ProxyFactory接口JavassistProxyFactory实现类中,getInvoker方法内部通过匿名内部类实现了doInvoke抽象方法。
Result接口主要定义了RPC 调用的相关方法,如下:
package com.alibaba.dubbo.rpc;import java.util.Map;public interface Result {Object getValue();Throwable getException();boolean hasException();Object recreate() throws Throwable;@DeprecatedObject getResult();Map<String, String> getAttachments();String getAttachment(String key);String getAttachment(String key, String defaultValue);}
RpcResult是对Result接口的一个实现。可看作对传入对象Object的一个包装,部分源码如下:
public class RpcResult implements Result, Serializable {private static final long serialVersionUID = -6925924956850004727L;private Object result;private Throwable exception;private Map<String, String> attachments = new HashMap<String, String>();public RpcResult() {}public RpcResult(Object result) {this.result = result;}public RpcResult(Throwable exception) {this.exception = exception;}public Object recreate() throws Throwable {if (exception != null) {throw exception;}return result;}
}
这就是Dubbo服务发布的Invoker生成过程
转载于:https://my.oschina.net/LucasZhu/blog/1833087
Dubbo服务服务暴露之ProxyFactory Invoker相关推荐
- Dubbo学习记录(十六)--服务调用【二】 - Invoker的调用、ProxyFactory、Protocol、Filter,Exchanger, Transporter扩展点
服务调用的前置学习[二] 服务调用涉及到的东西比较多, 需要一个个的理解透彻, 最终才能串起来: 服务端DubboInvoker的包装 DubboInvoker的生成是在服务导出的过程中创建的:由于D ...
- 阿里面试官:你知道Dubbo的服务暴露机制么?
点赞再看,养成习惯,微信搜一搜[三太子敖丙]关注这个喜欢写情怀的程序员. 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点.资料以及我的系 ...
- 深入解析 Dubbo 3.0 服务端暴露全流程
简介:随着云原生时代的到来,Dubbo 3.0 的一个很重要的目标就是全面拥抱云原生.正因如此,Dubbo 3.0 为了能够更好的适配云原生,将原来的接口级服务发现机制演进为应用级服务发现机制. 作者 ...
- Dubbo服务端暴露全流程
本文来说下Dubbo服务端暴露全流程 文章目录 概述 什么是应用级服务发现 服务端暴露全流程 暴露injvm协议的服务 注册service-discovery-registry协议 暴露Triple协 ...
- Dubbo服务端服务发布(一)Invoker创建
在Dubbo的服务发布过程中,Invoker的构造是一个重要的步骤,Invoker代表的是一个可以调用的服务的接口.它的定义如下: public interface Invoker<T> ...
- dubbo源码分析7 之 服务本地暴露
在上一篇文章我们分析了一下 dubbo 在服务暴露发生了哪些事,今天我们就来分析一下整个服务暴露中的本地暴露.(PS:其实我感觉本地暴露蛮鸡肋的).本地暴露需要服务提供方与服务消费方在同一个 JVM. ...
- Dubbo之服务导入流程解析
Dubbo之服务导入流程解析 接着上回<Dubbo之服务暴露流程浅析>,上一篇文章已经介绍完了Dubbo的服务提供者的服务暴露的整个流程,本文主要介绍Dubbo服务消费者的服务导入流程. ...
- Dubbo笔记 ⑤ : 服务发布流程 - Protocol#export
文章目录 一.前言 二.RegistryProtocol#export 1. URL解析 1.1 获取注册中心URL 1.2 获取服务URL 1.3 获取订阅URL 2. 服务暴露 3. 服务注册 4 ...
- Dubbo笔记 ㉘ : 服务自省-消费者
文章目录 一.前言 二.ReferenceAnnotationBeanPostProcessor#doGetInjectedBean 1. newProxyInstance 2. ReferenceB ...
- Dubbo笔记 ㉗ : 服务自省-提供者
文章目录 一.前言 1. 概念 二.服务自省 1. 相关配置 3.1 dubbo.application.metadata-type 3.2 dubbo.application.register-co ...
最新文章
- noip2019集训测试赛(五)
- android 图片气泡,android图片上显示气泡消息
- golang reflect
- 大学生动漫网页设计模板 机动战士高达静态网页制作成品下载 HTML漫画网页作业带JS轮播图
- java数组有顺序吗_java – 使用特定顺序对(数组)列表进行排序
- JAVA 数据类型数组
- 常见的几种 RuntimeException
- python—列表,元组,字典
- 正在发生的景象--从大众消费到圈层经济
- 简易支付系统的架构设计
- Google浏览器升级为最新打开网页时缓慢 “正在建立安全连接..........”解决方法
- Windows 10简单搭建一个局域网Web下载分享界面
- 3D资产大掌柜—Connecter
- 强世功:中美“关键十年” ——“新罗马帝国”与“新的伟大斗争”
- 刷题体验第一天——《录鼎记》第一章
- HarmonyOS实现点亮LED
- Java --- JVM动态链接与方法调用
- 深入学习理解Java集合
- [译]Unity3D Shader教程(二)HLSL
- ubuntu 下myeclipse下载,安装,破解
热门文章
- Adopt Open JDK官方文档(八)OpenJDK 项目介绍
- 68.TextView设置中划线、下划线
- 演示:扩展ACL的配置与应用技巧
- jsonp多次请求报错 not a function的解决方法
- VS2010与.NET4系列 10. VS2010代码智能感知增强
- cocos2d-x学习笔记10:动作3:补间动作
- java获取取得Timestamp类型的当前系统时间
- 路由子系统之fib相关结构体
- Ceph 撸源码系列(二):Ceph源代码里的那些锁 std::mutex(2 of 3)
- echart 地图 某个地区_「省份」Echart系列 | 绘制世界地图含中国各个省份(地图篇)(一) - seo实验室...