前言
上一篇文章解释了dubbo-spi的实现原理,这篇文章介绍如何暴露一个接口服务
正文
刚开始使用dubbo的使用,使用了XML配置去配置服务:
表示了DemoService这个接口,依赖了domoService这个bean,表示我们使用DemoService这个接口去请求dubbo服务器,会调用DemoServiceImpl这个实现类去处理。
dubbo:service是dubbo自定义的xml方式,bean标签则是属于spring,而spring也提供了自定义xml解析方式,,检查一下dubbo-config-spring这个包。
可以看到dubbo.xsd文件,里面规定了dubbo-xml所有标签以及参数:
看spring.handlers内部填写的解析类
使用了DubboBeanDefinitionParser,继承spring的BeanDefinitionParser,用于xml的解析
这个类里面内容写得很混乱,把所有的配置项全融合在一起写,大体思路就是解析xml,根据传入的class类型作出不同的解析,然后将类实例化并且给set或者is开头的方法注入值;根据上一张图片可以看出,service配置是由ServiceBean这个类来解析的。
ServiceBean这个类的继承和实现接口关系如下:
继承了spring的一些接口都与bean相关,而真正有用的是ApplicationListener,这个接口是一个Listener接口,ContextRefreshedEvent表明了是在这个类初始化完毕时执行该方法
查看该方法:
在ServiceBean初始化完毕后,检查状态,然后开始暴露服务
export方法交给了它的父类去执行,ServiceBean只是作为一个bean存在,真正干活的是ServiceConfig类
可以看到这就是暴露服务的核心方法,相比于xml配置方法,还有一种使用API配置方法,看一下xml和api配置的对比:
1 | java复制代码 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"META-INF/spring/dubbo-demo-provider.xml"}); |
这是xml配置方法的启动类
1 | java复制代码ServiceConfig<DemoService> serviceConfig = new ServiceConfig<DemoService>(); |
只需要执行export方法,就能将dubbo服务启动,说明ServiceConfig不仅做了服务暴露的事情,还把做了注册中心给一并添加了,先看export内部
同步方法,判断一些null值并获取,对延迟属性的判断,主要方法进入doExport
这一长段方法,主要是对监控、协议、注册中心、接口、实现类等的一些判断,然后进入 doExportUrls方法。
这里的protocols和registryURLs对应了xml上面的这两个部分,把注册中心配置转变成URL格式,其格式为:
主要是:ip-路径(类名)-param,param除了xml配置的一些属性外,还有dubbo版本,时间戳等。
在生成了注册中心URL和协议后,交给doExportUrlsFor1Protocol处理,
这个方法很长,前面很大一部分都是在构造URL,最后构造的URL如下所示:
根据不同协议和配置的参数,构造出这样一个URL,包含的信息全部在URL中。
最关键是这一段代码
proxyFactory是一个spi方法,默认使用JavassistProxyFactory,这里将上面的url的param和registryURL拼接在一起
这里将实现类用wrapper包装了一下,然后返回了一个AbstractProxyInvoker,内部调用了wrapper的invokeMethod方法,这个方法和反射类似
进入Wrapper内部
注意这个makeWrapper
使用Javassist,使用builder构造字节码,反编译出来是这样:
1 | java复制代码package org.apache.dubbo.common.bytecode; |
继承了Wrapper,实现了invokeMethod方法,根据方法的名称来反射调用方法,如果是多个方法那就是多个if操作而已
到目前为止,已经将需要暴露的服务实例包装起来了,下面就是将这个服务器暴露出去了。
所支持的协议如包名所见,默认为dubbo
调用Protocol的export方法暴露服务,默认使用dubbo
看DubboProtocol
主要是这个openServer方法
进入createServer
这里绑定了一个服务器和用于处理请求的hander
使用了tranposrt,属于dubbo-remoting层
tranposrt也是一个spi,默认使用netty,也可以跟换为其他比如http,根据xml配置构造成URL,选择不同的服务主要是在URL的param参数里面体现
打开一个nettyServer的方法,和经典netty方法差不多,主要做了一些封装。
到此为止,已经开启了一个netty服务器,绑定了指定端口号,并且将配置的service的实现类包装起来,通过netty服务器的请求,填入指定接口名称、方法名称以及参数,就可以获取invoker然后调用invokeMethod方法调用实现类的方法,实现了一次RPC
本文转载自: 掘金