服务暴露触发
关于服务暴露是怎么被触发的在之前的博客 dubbo与spring 中有简单介绍过。
大体步骤如下:
- 在xml中进行服务配置。
- 根据spring的schema扩展注册的
DubboBeanDefinitionParser
,将dubbo相关配置解析成对应的 BeanDefinition。 - BeanDefinition 转换为具体的 Bean 是在spring容器完成
refresh()
的过程中
3.1 设置delay且不为-1。ServiceBean
实现了InitializingBean
,在钩子方法afterPropertiesSet()
中触发 export,也就是 bean 在实例化后且在调用<init-method>
之前调用。
3.2 未设置delay或值为-1 。ServiceBean
实现了ApplicationListener
可以监听spring的相关的事件,在spring容器refresh()
完后,在onApplicationEvent()
完成事件的处理,进而触发 export。
服务暴露过程
服务暴露的过程中比较重要的是在ServiceConfig.doExportUrlFor1Protocol()
方法内,会生成具体服务对应的Provider URL后,同时如果存在注册中心还会在URL上加上registry,通过dubbo扩展机制获取ProxyFactory
的实现来得到Invoker
,然后调用Protocol
进行服务暴露。
dubbo中
ProxyFactory
扩展实现类有 Javassist 和 JDK 两种方式,默认使用 Javassist 是因为通过字节码操作生成相应的 wrapper类(第一次使用后会将实例化对象缓存起来),避免了每次调用使用Java反射导致的性能低下问题。
|
|
Invoker导出为Exporter分为两种情况:一种是registry协议类型,另一种是其他类型。
这里值的注意的是protocol
实际上是自适应类Protocol$Adaptive
,因而在运行时是根据URL来动态指定扩展点的实现类,在服务暴露过程中由于URL加上了registry,所以 Protocol 实现类是RegistryProtocol
。
同时,Protocol$Adaptive
在通过ExtensionLoader.getExtension()
获取具体实现类时,会加上一些装饰类的功能(eg: ProtocolFilterWrapper
和ProtocolListenerWrapper
),这两种装饰类只会对非RegistryProtocol
起作用。
当RegistryProtocol
进行服务暴露的过程中,会首先调用doLocalExport()
,通过默认的DubboProtocol.export()
对 Provider URL 进行服务暴露。然后再根据具体的 Registry 进行服务注册和监听器注册,并订阅override数据。
等到真正的DubboProtocol
进行服务暴露时,会启动一个服务监听server,通过调用Exchanger
和Transporter
层的扩展实现完成的。