Dubbo ServiceBean启动源码解析

蔚落 2022-05-24 10:37 266阅读 0赞

前言

spring2.5以后,spring支持自定义schema扩展xml配置。具体的spring schema细节,本文就不多说了。这篇文章就拿provider为例,介绍dubbo是如何启动服务的。

正文

首先,再把HelloWolrd例子中的 provider.xml的源码放上来

Xml代码 收藏代码

  1. <?**xml version=”1.0” encoding=”UTF-8”?>**
  2. <**beans** xmlns=”http://www.springframework.org/schema/beans“
  3. xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance“
  4. xmlns:dubbo=”http://code.alibabatech.com/schema/dubbo“
  5. xsi:schemaLocation=”http://www.springframework.org/schema/beans
  6. http://www.springframework.org/schema/beans/spring-beans.xsd
  7. http://code.alibabatech.com/schema/dubbo
  8. http://code.alibabatech.com/schema/dubbo/dubbo.xsd
  9. >
  10. <**dubbo:application name=”hello-world-app” />**
  11. <**dubbo:registry protocol=”zookeeper” address=”10.125.195.174:2181” />**
  12. <**dubbo:protocol name=”dubbo” port=”20880” />**
  13. <**dubbo:service** interface=”demo.service.DemoService”
  14. ref=”demoService” />
  15. <**bean id=”demoService” class=”demo.service.DemoServiceImpl” />**
  16. </**beans**>

    对应的自定义schema文件,就不解释了。直接在dubbo-{version}.jar 中 META-INF目录下找到对应的handler配置

spring.handlers 写道

http\://code.alibabatech.com/schema/dubbo=com.alibaba.dubbo.config.spring.schema.DubboNamespaceHandler

可以看到,对应的handler是 DubboNamespaceHandler。对应的源码如下

Java代码 收藏代码

  1. public class DubboNamespaceHandler extends NamespaceHandlerSupport {
  2. static {
  3. Version.checkDuplicate(DubboNamespaceHandler.class);
  4. }
  5. public void init() {
  6. registerBeanDefinitionParser(“application”, new DubboBeanDefinitionParser(ApplicationConfig.class, true));
  7. registerBeanDefinitionParser(“module”, new DubboBeanDefinitionParser(ModuleConfig.class, true));
  8. registerBeanDefinitionParser(“registry”, new DubboBeanDefinitionParser(RegistryConfig.class, true));
  9. registerBeanDefinitionParser(“monitor”, new DubboBeanDefinitionParser(MonitorConfig.class, true));
  10. registerBeanDefinitionParser(“provider”, new DubboBeanDefinitionParser(ProviderConfig.class, true));
  11. registerBeanDefinitionParser(“consumer”, new DubboBeanDefinitionParser(ConsumerConfig.class, true));
  12. registerBeanDefinitionParser(“protocol”, new DubboBeanDefinitionParser(ProtocolConfig.class, true));
  13. registerBeanDefinitionParser(“service”, new DubboBeanDefinitionParser(ServiceBean.class, true));
  14. registerBeanDefinitionParser(“reference”, new DubboBeanDefinitionParser(ReferenceBean.class, false));
  15. registerBeanDefinitionParser(“annotation”, new DubboBeanDefinitionParser(AnnotationBean.class, true));
  16. }
  17. }

    从这里也可以看到,对应的支持的标签其实不多。所有的Parser都封装到了DubboBeanDefinitionParser中。对应的class,就是传入的beanClass。比如application的就是ApplicationConfig。module的就是ModuleConfig。经过Parser的转换,provider.xml大概可以变成如下的样子(具体的解析不多解释了)

Xml代码 收藏代码

  1. <**bean id=”hello-world-app” class=”com.alibaba.dubbo.config.ApplicationConfig”/>**
  2. <**bean id=”registryConfig” class=”com.alibaba.dubbo.config.RegistryConfig”>**
  3. <**property name=”address” value=”10.125.195.174:2181”/>**
  4. <**property name=”protocol” value=”zookeeper”/>**
  5. </**bean**>
  6. <**bean id=”dubbo” class=”com.alibaba.dubbo.config.ProtocolConfig”>**
  7. <**property name=”port” value=”20880”/>**
  8. </**bean**>
  9. <**bean id=”demo.service.DemoService” class=”com.alibaba.dubbo.config.spring.ServiceBean”>**
  10. <**property name=”interface” value=”demo.service.DemoService”/>**
  11. <**property name=”ref” ref=”demoService”/>**
  12. </**bean**>
  13. <**bean id=”demoService” class=”demo.service.DemoServiceImpl” />**

分别看每一个bean的内容。由于篇幅原因,我就不把每个代码放上来了。总结一下就是

写道

ApplicationConfig,RegistryConfig,ProtocolConfig都只是普通的pojo。负责接收数据。真正的处理逻辑在ServiceBean中

看具体的代码

Java代码 收藏代码

  1. public class ServiceBean extends ServiceConfig implements InitializingBean, DisposableBean, ApplicationContextAware, ApplicationListener, BeanNameAware {
  2. private static final long serialVersionUID = 213195494150089726L;
  3. private static transient ApplicationContext SPRING_CONTEXT;
  4. private transient ApplicationContext applicationContext;
  5. private transient String beanName;
  6. private transient boolean supportedApplicationListener;
  7. public ServiceBean() {
  8. super();
  9. }
  10. public ServiceBean(Service service) {
  11. super(service);
  12. }
  13. public static ApplicationContext getSpringContext() {
  14. return SPRING_CONTEXT;
  15. }
  16. //设置对应的applicationConext
  17. public void setApplicationContext(ApplicationContext applicationContext) {
  18. this.applicationContext = applicationContext;
  19. SpringExtensionFactory.addApplicationContext(applicationContext);
  20. if (applicationContext != null) {
  21. SPRING_CONTEXT = applicationContext;
  22. try {
  23. Method method = applicationContext.getClass().getMethod(“addApplicationListener”, new Class<?>[]{ApplicationListener.class}); // 兼容Spring2.0.1
  24. method.invoke(applicationContext, new Object[] { this});
  25. supportedApplicationListener = true;
  26. } catch (Throwable t) {
  27. if (applicationContext instanceof AbstractApplicationContext) {
  28. try {
  29. Method method = AbstractApplicationContext.class.getDeclaredMethod(“addListener”, new Class<?>[]{ApplicationListener.class}); // 兼容Spring2.0.1
  30. if (! method.isAccessible()) {
  31. method.setAccessible(true);
  32. }
  33. method.invoke(applicationContext, new Object[] { this});
  34. supportedApplicationListener = true;
  35. } catch (Throwable t2) {
  36. }
  37. }
  38. }
  39. }
  40. }
  41. public void setBeanName(String name) {
  42. this.beanName = name;
  43. }
  44. public void onApplicationEvent(ApplicationEvent event) {
  45. //如果容器加载完成以后当前的provider还没export,那么调用一次export方法(这个针对那种延迟export的情况)
  46. if (ContextRefreshedEvent.class.getName().equals(event.getClass().getName())) {
  47. if (isDelay() && ! isExported() && ! isUnexported()) {
  48. if (logger.isInfoEnabled()) {
  49. logger.info(“The service ready on spring started. service: “ + getInterface());
  50. }
  51. export();
  52. }
  53. }
  54. }
  55. //是否延迟export
  56. private boolean isDelay() {
  57. Integer delay = getDelay();
  58. ProviderConfig provider = getProvider();
  59. if (delay == null && provider != null) {
  60. delay = provider.getDelay();
  61. }
  62. return supportedApplicationListener && (delay == null || delay.intValue() == -1);
  63. }
  64. @SuppressWarnings({ “unchecked”, “deprecation” })
  65. public void afterPropertiesSet() throws Exception {
  66. //这里的Provider其实就是ProviderConfig对象。如果provider为空,表示spring在创建 当前bean的时候还没有初始化ProtocolConfig bean。这里就是做一个前后顺序保证
  67. if (getProvider() == null) {
  68. Map providerConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class, false, false);
  69. if (providerConfigMap != null && providerConfigMap.size() > 0) {
  70. Map protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);
  71. if ((protocolConfigMap == null || protocolConfigMap.size() == 0)
  72. && providerConfigMap.size() > 1) { // 兼容旧版本
  73. List providerConfigs = new ArrayList();
  74. for (ProviderConfig config : providerConfigMap.values()) {
  75. if (config.isDefault() != null && config.isDefault().booleanValue()) {
  76. providerConfigs.add(config);
  77. }
  78. }
  79. if (providerConfigs.size() > 0) {
  80. setProviders(providerConfigs);
  81. }
  82. } else {
  83. ProviderConfig providerConfig = null;
  84. for (ProviderConfig config : providerConfigMap.values()) {
  85. if (config.isDefault() == null || config.isDefault().booleanValue()) {
  86. if (providerConfig != null) {
  87. throw new IllegalStateException(“Duplicate provider configs: “ + providerConfig + “ and “ + config);
  88. }
  89. providerConfig = config;
  90. }
  91. }
  92. if (providerConfig != null) {
  93. setProvider(providerConfig);
  94. }
  95. }
  96. }
  97. }
  98. //这里和上面同样,手动创建ApplicationConfig bean
  99. if (getApplication() == null
  100. && (getProvider() == null || getProvider().getApplication() == null)) {
  101. Map applicationConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class, false, false);
  102. if (applicationConfigMap != null && applicationConfigMap.size() > 0) {
  103. ApplicationConfig applicationConfig = null;
  104. for (ApplicationConfig config : applicationConfigMap.values()) {
  105. if (config.isDefault() == null || config.isDefault().booleanValue()) {
  106. if (applicationConfig != null) {
  107. throw new IllegalStateException(“Duplicate application configs: “ + applicationConfig + “ and “ + config);
  108. }
  109. applicationConfig = config;
  110. }
  111. }
  112. if (applicationConfig != null) {
  113. setApplication(applicationConfig);
  114. }
  115. }
  116. }
  117. //如果没有创建module,则手动创建 module。 在HelloWorld例子中,没有用到module。
  118. if (getModule() == null
  119. && (getProvider() == null || getProvider().getModule() == null)) {
  120. Map moduleConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class, false, false);
  121. if (moduleConfigMap != null && moduleConfigMap.size() > 0) {
  122. ModuleConfig moduleConfig = null;
  123. for (ModuleConfig config : moduleConfigMap.values()) {
  124. if (config.isDefault() == null || config.isDefault().booleanValue()) {
  125. if (moduleConfig != null) {
  126. throw new IllegalStateException(“Duplicate module configs: “ + moduleConfig + “ and “ + config);
  127. }
  128. moduleConfig = config;
  129. }
  130. }
  131. if (moduleConfig != null) {
  132. setModule(moduleConfig);
  133. }
  134. }
  135. }
  136. //初始化registiry
  137. if ((getRegistries() == null || getRegistries().size() == 0)
  138. && (getProvider() == null || getProvider().getRegistries() == null || getProvider().getRegistries().size() == 0)
  139. && (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().size() == 0)) {
  140. Map registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false);
  141. if (registryConfigMap != null && registryConfigMap.size() > 0) {
  142. List registryConfigs = new ArrayList();
  143. for (RegistryConfig config : registryConfigMap.values()) {
  144. if (config.isDefault() == null || config.isDefault().booleanValue()) {
  145. registryConfigs.add(config);
  146. }
  147. }
  148. if (registryConfigs != null && registryConfigs.size() > 0) {
  149. super.setRegistries(registryConfigs);
  150. }
  151. }
  152. }
  153. //初始化monitor (HelloWorld例子中没有用到)
  154. if (getMonitor() == null
  155. && (getProvider() == null || getProvider().getMonitor() == null)
  156. && (getApplication() == null || getApplication().getMonitor() == null)) {
  157. Map monitorConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class, false, false);
  158. if (monitorConfigMap != null && monitorConfigMap.size() > 0) {
  159. MonitorConfig monitorConfig = null;
  160. for (MonitorConfig config : monitorConfigMap.values()) {
  161. if (config.isDefault() == null || config.isDefault().booleanValue()) {
  162. if (monitorConfig != null) {
  163. throw new IllegalStateException(“Duplicate monitor configs: “ + monitorConfig + “ and “ + config);
  164. }
  165. monitorConfig = config;
  166. }
  167. }
  168. if (monitorConfig != null) {
  169. setMonitor(monitorConfig);
  170. }
  171. }
  172. }
  173. //初始化protocol
  174. if ((getProtocols() == null || getProtocols().size() == 0)
  175. && (getProvider() == null || getProvider().getProtocols() == null || getProvider().getProtocols().size() == 0)) {
  176. Map protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);
  177. if (protocolConfigMap != null && protocolConfigMap.size() > 0) {
  178. List protocolConfigs = new ArrayList();
  179. for (ProtocolConfig config : protocolConfigMap.values()) {
  180. if (config.isDefault() == null || config.isDefault().booleanValue()) {
  181. protocolConfigs.add(config);
  182. }
  183. }
  184. if (protocolConfigs != null && protocolConfigs.size() > 0) {
  185. super.setProtocols(protocolConfigs);
  186. }
  187. }
  188. }
  189. //设置服务名称。
  190. if (getPath() == null || getPath().length() == 0) {
  191. if (beanName != null && beanName.length() > 0
  192. && getInterface() != null && getInterface().length() > 0
  193. && beanName.startsWith(getInterface())) {
  194. setPath(beanName);
  195. }
  196. }
  197. //调用export
  198. if (! isDelay()) {
  199. export();
  200. }
  201. }
  202. //调用unexport
  203. public void destroy() throws Exception {
  204. unexport();
  205. }
  206. }

代码里面已经加了一些注释。虽然很长,逻辑还是很简单的。其中用到了spring的很多特性。非常值得我们学习

发表评论

表情:
评论列表 (有 0 条评论,266人围观)

还没有评论,来说两句吧...

相关阅读

    相关 dubbo

    dubbo源码解析-网络通信 在之前的内容中,我们讲解了消费者端服务发现与提供者端服务暴露的相关内容,同时也知道消费者端通过内置的负载均衡算法获取合适的调用invoker进行