ServiceBean概述
ServiceBean是Dubbo中很重要的一个类,每个暴露出去的服务都会生成一个ServiceBean,ServiceBean的继承关系如下图。
ServiceBean继承自ServiceConfig,ServiceConfig是服务暴露的具体实现类。另外ServiceBean还实现了InitializingBean,DisposableBean,ApplicationContextAware,ApplicationListener,BeanNameAware,
ApplicationEventPublisherAware几个接口,简单介绍下几个接口的作用:
继承InitializingBean实现其afterPropertiesSet方法,对象实例化完毕后,调用该方法。
继承ApplicationListener接口,监听上下文监听事件contextrefreshedevent事件,当Spring容器启动完成后会发布该事件,监听到之后会执行onApplicationEvent()方法。
继承DisposableBean实现其destory()方法,在实例生命周期结束前,会调用该方法。
继承BeanNameWare,用于设置Bean的名称
继承ApplicationContextAware,用于获取Spring容器的上下文
继承ApplicationEventPublisherAware接口,用于发布事件。
源码分析
ServiceBean继承了InitializingBean接口,所以,实例化之后就会调用其afterPropertiesSet()方法。afterPropertiesSet()方法实现有点长,就不展开描述了,其功能主要是对ProviderConfig、ApplicationConfig、ModuleConfig、RegistryConfig、MetadataConfig、ConfigCenter、MonitorConfig等配置Bean的处理,如果标签未配置,会从Spring容器中获取这些配置,然后设置到当前的ServiceBean中。最后会判断当前是否支持事件监听机制,如果不支持,就会在最后通过export()方法暴露Dubbo服务。
ServiceBean实现了ApplicationListener接口,当ApplicationContext启动完成事件后调用其onApplicationEvent()方法如下:
此处会调用其父类的ServiceConfig的export方法完成服务暴露,代码实现如下:
此方法中主要做了检查属性的配置,并且根据配置的优先级进行属性的覆盖,初始化ServiceMetadata,检查配置逻辑还是蛮长的,此处只关注服务暴露流程,就不展开介绍了,直接进入doExport()方法:
对所有配置的协议进行服务暴露,此处只配置了一个dubbo协议,所以就只暴露dubbo,继续跟进到doExportUrlsFor1Protocol()方法进行服务暴露,doExportUrlsFor1Protocol()方法实现也是非常之长,大部分篇幅用于属性配置的处理工作,本文只关注服务暴露相关,代码如下:
注释出自Dubbo配置属性初始化解析,感谢大佬详细的注释,才能让初学者节省了大量的学习成本。
前部分主要通过反射获取配置对象并放到map用于后续构造URL参数,然后以URL为基础暴露服务。
服务暴露主要分为injvm和registry,即本地服务暴露和远程服务暴露,区别在于远程服务暴露还会将服务注册信息registryURL等通过动态代理转换成Invoker,使用export作为key追加服务元数据信息,远程服务暴露时也会根据相应协议在本地进行一次服务暴露,可以本地服务直连。
此方法主要做的是服务暴露的前置工作,其暴露逻辑主要位于RegitryProtocol#export方法,代码实现如下:
注释出自大佬的另一篇文章Dubbo服务暴露与注册,其主要功能是,首先委托具体协议(此处为Dubbo)进行服务暴露,创建NettyServer(默认为Netty)监听端口和保存服务实例,然后创建注册中心对象,与注册中心创建TCP链接,注册服务元数据到注册中心,订阅configurators节点,监听服务动态属性变更事件,设置相关的URL对象,并且使用DestroyableExporter对exporter进行封装返回。
服务暴露调用了doLocalExport()方法,因为此处最终使用dubbo协议进行服务暴露,所以最终调用DubboProtocol#export方法,代码如下:
主要实现为根据服务分组、版本、服务接口和暴露端口作为key用于关联具体服务Invoker,注册stub事件分发器,服务初次暴露会创建监听服务器,此时会触发HeaderExchanger中的绑定方法,最终调用NettyServer进行处理,一个标准的Netty服务器启动流程,详细后续介绍。最后注册序列化类。
至此,一个服务暴露流程基本介绍完毕。