Dubbo源码学习--服务发布(ProxyFactory、Invoker)
上文分析了Dubbo服务发布的整体流程,但服务代理生成的具体细节介绍得还不是很详细。下面将会接着上文继续分析。上文介绍了服务代理生成的切入点,如下:
Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);
这里的proxyFactory是在ServiceConfig中定义的,是final类型静态变量,赋值后无法进行修改。如下:
private static final ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
proxyFactory通过ExtensionLoader拓展机制进行加载。查看ProxyFactory接口源码如下:
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;
@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(具体是如何实现配置的,这里就不讲了,详见Dubbo SPI拓展机制)。
下面来重点看看JavassistProxyFactory代理工厂。
JavassistProxyFactory继承实现关系图如下:
JavassistProxyFactory源码非常简单,只有两个方法:
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;
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));
}
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) {
@Override
protected 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;
@Deprecated
Object 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生成过程,下节将继续分析Dubbo服务发布的服务暴露过程
如果对您有帮助,不妨点个赞、关注一波
Dubbo源码学习--服务发布(ProxyFactory、Invoker)的更多相关文章
- Dubbo源码学习--服务发布(ServiceBean、ServiceConfig)
前面讲过Dubbo SPI拓展机制,通过ExtensionLoader实现可插拔加载拓展,本节将接着分析Dubbo的服务发布过程. 以源码中dubbo-demo模块作为切入口一步步走进Dubbo源码. ...
- Dubbo源码学习--服务发布(DubboProtocol、Exporter)
在Dubbo服务发布的整体流程一文中,只是分析了服务发布的整体流程,具体的细节还没有进一步分析.本节将继续分析服务暴露的过程.在ServiceConfig中通过一句话即可暴露服务,如下: Export ...
- Dubbo源码学习--服务是如何发布的
相关文章: Dubbo源码学习--服务是如何发布的 Dubbo源码学习--服务是如何引用的 ServiceBean ServiceBean 实现ApplicationListener接口监听Conte ...
- Dubbo源码学习--服务是如何引用的
ReferenceBean 跟服务引用一样,Dubbo的reference配置会被转成ReferenceBean类,ReferenceBean实现了InitializingBean接口,直接看afte ...
- dubbo源码之服务发布与注册
服务端发布流程: dubbo 是基于 spring 配置来实现服务的发布的,对于dubbo 配置文件中看到的<dubbo:service>等标签都是服务发布的重要配置 ,对于这些提供可配置 ...
- dubbo源码之四——服务发布二
dubbo版本:2.5.4 2. 服务提供者暴露一个服务的详细过程 上图是服务提供者暴露服务的主过程: 首先ServiceConfig类拿到对外提供服务的实际类ref(如:HelloWorldImpl ...
- 2、Dubbo源码解析--服务发布原理(Netty服务暴露)
一.服务发布 - 原理: 首先看Dubbo日志,截取重要部分: 1)暴露本地服务 Export dubbo service com.alibaba.dubbo.demo.DemoService to ...
- Dubbo源码学习文章目录
目录 Dubbo源码学习--服务是如何发布的 Dubbo源码学习--服务是如何引用的 Dubbo源码学习--注册中心分析 Dubbo源码学习--集群负载均衡算法的实现
- dubbo源码学习(四):暴露服务的过程
dubbo采用的nio异步的通信,通信协议默认为 netty,当然也可以选择 mina,grizzy.在服务端(provider)在启动时主要是开启netty监听,在zookeeper上注册服务节点, ...
随机推荐
- 开发手机APP的神器 --- ionic
前 言 在如今的生活中,手机已经与我们的生活紧紧的联系在了一起.而手机APP更是其中,重要的一环.今天,影子就为大家介绍一种开发手机APP的超级神器---ionic. ioni ...
- Mybatis Generator生成Mybatis Dao接口层*Mapper.xml以及对应实体类
[前言] 使用Mybatis-Generator自动生成Dao.Model.Mapping相关文件,Mybatis-Generator的作用就是充当了一个代码生成器的角色,使用代码生成器不仅可以简化我 ...
- Go语言之三驾马车
作者:唐郑望,腾讯后台开发 工程师商业转载请联系腾讯WeTest获得授权,非商业转载请注明出处. WeTest 导读 Go语言的三个核心设计: interface | goroutine | cha ...
- python实现进度条和百分比同时显示
python中同时打印进度条和百分比 仅打印进度条: import sys,time for i in range(100): sys.stdout.write('>') sys.stdout. ...
- Linux系列教程(十)——Linux文本编辑器vim
通过前面几篇博客我们终于结束了Linux常用命令的介绍,Linux常用命令主要包括以下: ①.Linux文件和目录处理命令 ②.Linux链接命令和权限管理命令 ③.Linux文件搜索命令 ④.Lin ...
- H5新特性汇总
H5新特性: 新增选择器 document.querySelector.document.querySelectorAll 拖拽释放(Drag and drop) API 媒体播放的 video 和 ...
- spring mvc常用注解的说明
最近一段时间学习了springboot,所以熟悉一下mvc中常用的注解,这样可以方便开发 简介: @RequestMapping RequestMapping是一个用来处理请求地址映射的注解,可用于类 ...
- MicroService.Core简易微服务框架《一、简介》
MicroService.Core MicroService.Core 的初衷是为了方便的创建一个微服务, 可作为 Windows Service 或者控制台模式启动. 它底层使用了 OWin 自托管 ...
- Max Sum Plus Plus
A - Max Sum Plus Plus Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I6 ...
- Python函数篇:dict函数和列表生成式
1.dict函数语法:dict()dict(**kwarg) dict(mapping, **kwarg) dict(iterable, **kwarg) 第一种:dict()构造一个空字典 h=di ...