先来看我们的provider.xml的配置文件
这个文件的重要性肯定重要,那么这些标签是怎么来的呢?
其实就是spring自定义标签来的,在源码中我们可以看到,
继续看spring.handlers文件中内容
可以看得出这个DubboNamespaceHandler应该很重要,最后可以找出他的所在位置,同时还发现同目录下还有DubboBeanDefinitionParser类似于spring中BeanDefinitionParser。DubboNamespaceHandler类似于spring中NamespaceHandler:
再进去看看里面到底做了些什么东东
可以看到
DubboBeanDefinitionParser继承spring的BeanDefinitionParser,DubboNamespaceHandlerSupport继承spring的NamespaceHandlerSupport,NamespaceHandlerSupport继承NamespaceHandler。由此可以知道这个provider.xml配置文件的解析其实就是和spring一样解析。
在这个spring目录下我们看到这两个类
这两个类非常重要:
ServiceBean服务端发布入口
ReferenceBean客户端发布入口
先看看服务端的服务是怎么发布的
他是实现spring的这几类来做的。所以还是基于spring来做的
这个类中afterPropertiesSet()方法中。是否延迟加载
export()方法就是做了一些参数校验
不管是否延迟加载都会走doExport()方法,doExport()方法也是做一些参数校验 和配置项的校验
然后调用doExportUrls()
就是在provider.xml中配置多个protocol
doExportUrlsFor1Protocol中 1:使用各种方法获取本地ip 2:如果没有配置端口则
final int defaultPort = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(name).getDefaultPort();
获取默认端口dubbo默认20880
3:拼凑url
dubbo://192.168.11.1:20880/com.tian.dubbo.IGpHello?anyhost=true&application=hello-world-app&default.delay=10&delay=10&dubbo=2.5.6&generic=false&interface=com.tian.dubbo.IGpHello&methods=sayHello&pid=121964&side=provider×tamp=1529758790987
然后
debug到此
这里有个Invoker对象为
所以我们可以把Invoker对象理解为服务的代理对象。
如果没有配置注册中心,
protocol
----->Protocol$Adaptive
---->ProtocolFilterWrapper(ProtocolListenerWrapper(DubboProtocol))。底层是基于netty协议去启动一个nettyserver
} else {//如果没有配置注册中心 Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url); Exporter<?> exporter = protocol.export(invoker);//dubbo exporters.add(exporter); }
Protocol extension = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(“registry”);
registry=com.alibaba.dubbo.registry.integration.RegistryProtocol
protocol=RegistryProtocol
RegistryProtocol的export方法源码
doLocalExport()本地发布
对缓存进行双重检查锁,如果有就直接返回,否则new一个
debug到此,相关属性对应的值:
exporter相关属性
此时相关值
上面
同样根据
Protocol extension =ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.rpc.Protocol.class).getExtension(“dubbo”);
protocol=DubboProtocol.这里并不是获得一个单纯的DubboProtocol扩展点,而是会通过Wrapper对Protocol进行装饰,装饰器分别为: ProtocolFilterWrapper/ ProtocolListenerWrapper;两个装饰类的源码为以下:
ProtocolFilterWrapper
这个类非常重要,dubbo机制里面日志记录、超时等等功能都是在这一部分实现的
这个类有3个特点,
第一它有一个参数为Protocol protocol的构造函数;
第二,它实现了Protocol接口;
第三,它使用责任链模式,对export和refer函数进行了封装;部分代码如下,上面的源码中ProtocolFilterWrapper有个buildInvokderChain()方法
public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException { //buildInvokerChain函数:它读取所有的filter类,利用这些类封装invoker
|
我们看如下文件:
/dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal/com.alibaba.dubbo.rpc.Filter
其实就是对Invoker,通过如下的Filter组装成一个责任链
echo=com.alibaba.dubbo.rpc.filter.EchoFilter |
这其中涉及到很多功能,包括权限验证、异常、超时等等,当然可以预计计算调用时间等等应该也是在这其中的某个类实现的;这里其实就是dubbo中AOP
这里我们可以看到export和refer过程都会被filter过滤
ProtocolListenerWrapper
在这里我们可以看到export和refer分别对应了不同的Wrapper;export是对应的ListenerExporterWrapper。这块暂时先不去分析,因为这个地方并没有提供实现类。
debug到此
exporterMap
createServer方法()
Exchangers.bind()方法
这里使用的是getExchange(url)=默认自适应扩展类HeaderExchanger
这里先去Transporters.bind()方法,
getTransporter().bind(url, handler);
这里的自适应扩展类就是默认的netty的
构造一个NettyServer
继续调用父类的方法
这个open()方法在这个父类里并没有实现,而是采用模板方法模式,由各自实现类自己去实现
到此本地发布已经结束。