avatar

Dubbo源码分析之服务注册发布(三)

ok!经过前面几篇的讲解,我们已经知晓了如下几个知识点:

  • Spring自定义Xml标签的解析
  • Dubbo xml标签解析的入口
  • Dubbo是如何解析xml配置的
  • Dubbo最后把解析的配置放到哪了。

既然配置已经解析完毕,那么下一步盲猜就是根据配置来发布服务了(针对provider来说)。那我们这篇就来谈谈Dubbo的服务发布,当然,肯定会分篇聊的。下面我们开始吧!

说明

从该篇起,我们就开始去着手分析Dubbo服务的发布和注册功能的实现了,该部分要涉及到的代码很多,而且也很绕。

你会在里面经常看到之前我们说过的SPI扩展类,所以有时候会晕,于是我会分几篇进行说明,每篇说一点,并且会对该篇的内容画个时序图,当然,时序图可能画的并不那么专业,但是总比没有的好(自我安慰~)。

这篇就是起个头,估计不会分析到真正核心的部分。

下面就让我们进入正题吧。

ServiceBean

还记得下面这张图么?

我们之前说过,里面有几个特殊的地方,也就是config-centerservicereference这几个标签在创建Parser的时候,第一个参数和其他的不同,其他都是xxxxConfig,只有这几个是xxxBean。我们今天先看看service标签所对应的ServiceBean

InitializingBean.afterPropertiesSet()

InitializingBean我们知道它是Spring的一个接口,里面只有一个afterPropertiesSet()方法,我们的类只要是实现了该接口,就必须得重写这个方法。

那么有什么用呢?Spring在我们xml解析之后,就会拿到所有实现了InitializingBean接口的bean,然后调用其afterPropertiesSet()方法。

也就是说,这个afterPropertiesSet()是在xml配置解析完成后调用。回到Dubbo,我们上一篇刚说完它的配置解析,那么我们可以想一下,既然配置解析完了,按照逻辑下一步是不是把服务初始化好,然后暴露出去,注册到zk或者其他注册中心上。

那么按照这个逻辑,然后dubbo又是依赖Spring的,然后刚好发现在ServiceBean上有实现这个接口,那么我们就尝试着下个断点,让它跑起来,看看是否可以断下。然后我们再继续往下分析。

看,断下来了,然后我们翻翻这个方法,发现在最后有如下代码:

1
2
3
4
//在前面做一些事...
if (!supportedApplicationListener) {
export();
}

看到export(),我们盲猜字面意识就是导出,导出什么呢?在这里只能是导出我们的服务了。也就是说afterPropertiesSet()方法在经过一系列操作后,最终会导出我们的服务,那么这一系列操作做了啥事呢?这就是该篇要分析的内容。

代码一共有200行左右,所以我们拆分下,分为几步去分析。把代码的if折叠下,刚好可以分为如下几部分

让我们一步一步的分析下去。

第一个if条件——设置Provider属性(已过时)

我们以这个if条件为例,剖析里面的实现,虽然Provider已经废弃,平常我们都是用<dubbo:service>来声明服务,但丝毫不影响我们通过这块代码来深入。后续的if体内都是差不多,所以有了这个基础,我们看后面的就很容易。

第一部分

1
2
3
4
if (getProvider() == null) {
Map<String, ProviderConfig> providerConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class, false, false);
//以下代码省略...
}

这里的getProvider()方法得到的是一个ProviderConfig对象,这里说如果是null,就会进我们的if体,那可以盲猜一下,在这个if体里肯定是为这个ProviderConfig赋值,具体是不是,我们还得往下分析去验证。

在这个if体里面,我们暂时只抠出了一行代码,这一行代码得拆分一下看。也就是如下这样:

  • 先判断applicationContext是不是为null,如果为null,直接把Map赋值为null。
  • 如果不为null,就会调BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProviderConfig.class, false, false),把得到的返回值赋给providerConfigMap

那么这里有两个问题。

  • applicationContext是什么时候赋值的,在哪里赋值的。
  • BeanFactoryUtils.beansOfTypeIncludingAncestors()是什么?有什么用?
第一个问题

我们先看看第一个问题,applicationContext是什么时候赋值的。我们碰到这个问题,第一反应是找applicationContext的调用,看看在哪用到了,发下在ServiceBean中有如下代码:

1
2
3
4
5
6
7
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
//在这里为applicationContext赋值。
this.applicationContext = applicationContext;
SpringExtensionFactory.addApplicationContext(applicationContext);
supportedApplicationListener = addApplicationListener(applicationContext, this);
}

我们可以看到,他是通过setApplicationContext()方法为applicationContext赋值的,然后细心的朋友已经发现在该方法上面有个@Override的注解,一般这个注解我们是在重写方法的时候会加上,那么肯定是ServiceBean有继承或者实现某个类或接口,这种情况才会发生重载,并且这里是Spring的applicationContext,那我们可以找找,是否有某个接口里面有该方法。最后发现是在ApplicationContextAware接口中有该方法。

这里就有一个知识点了,一般情况下,我们想拿到一个ApplicationContext对象会怎么操作?手动new一个?但是这又不是main方法,如果再new一个,不就有多个ApplicationContext了?所以这种直接new的方法是不可取的。那么怎么办呢?

Spring给我们提供了一种注入ApplicationContext的途径,也就是实现这个ApplicationContextAware接口,在Spring启动过后,就会调用其中的setApplicationContext()方法,把ApplicationContext对象传给我们。

那么第一个问题有答案了。下面来看第二个问题。

第二个问题

BeanFactoryUtils.beansOfTypeIncludingAncestors()是什么?有什么用?我们直接看这个方法的源码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//从传参来看,第一个参数是我们的ApplicationContext对象
//第二个参数是要匹配的类型,也就是我们要get到的类型
public static <T> Map<String, T> beansOfTypeIncludingAncestors(
ListableBeanFactory lbf, Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
throws BeansException {

Assert.notNull(lbf, "ListableBeanFactory must not be null");
Map<String, T> result = new LinkedHashMap<String, T>(4);
//这里是调用applicationContext的方法,获取一个Map
result.putAll(lbf.getBeansOfType(type, includeNonSingletons, allowEagerInit));
if (lbf instanceof HierarchicalBeanFactory) {
HierarchicalBeanFactory hbf = (HierarchicalBeanFactory) lbf;
if (hbf.getParentBeanFactory() instanceof ListableBeanFactory) {
Map<String, T> parentResult = beansOfTypeIncludingAncestors(
(ListableBeanFactory) hbf.getParentBeanFactory(), type, includeNonSingletons, allowEagerInit);
for (Map.Entry<String, T> entry : parentResult.entrySet()) {
String beanName = entry.getKey();
if (!result.containsKey(beanName) && !hbf.containsLocalBean(beanName)) {
result.put(beanName, entry.getValue());
}
}
}
}
return result;
}

这里我们采取调试的方法,来看看确定下下面几个地方的值。

  • lbf参数是什么类型,因为下面会调用它的getBeansOfType()方法。
  • getBeansOfType()方法具体是调用谁的,内部实现是怎么样的。

断点断下来后,这两个的值分别如下:

  • lbf参数类型:

    • 前面因为有说过,我们在dubbo中调用该方法,第一个参数传的是ApplicationContext,具体是哪个呢?截图如下:

  • getBeansOfType()方法具体是调用谁的,内部实现是怎么样的

    • 既然上面说,lbf具体的对象是ClassPathXmlApplicationContext,那我们现在就看一下源码,看看ClassPathXmlApplicationContext是怎么实现getBeansOfType()的吧。

    • 我们到ClassPathXmlApplicationContext中搜索getBeansOfType()发现该方法的实现是在其父类AbstractXmlApplicationContext中实现,如图:

    • 那我们就去它父类看下吧,记住,我们是要看getBeasOfType(Class,boolean,boolean)方法。

      1
      2
      3
      4
      public <T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit) throws BeansException {
      this.assertBeanFactoryActive();
      return this.getBeanFactory().getBeansOfType(type, includeNonSingletons, allowEagerInit);
      }

      很简单的两行代码,最后调用的是BeanFactorygetBeansOfType()方法,那这个BeanFactory是什么呢?我们发现它是一个抽象方法,如下:

      1
      public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;

      既然是抽象方法,那我们就得去找实现了,我们回到ClassPathXmlApplicationContext,然后ctrl+o输入这个方法名,看看能不能找到实现的地方,

      从上图来看,具体实现类是AbstractRefreshableApplicationContext,他实现如下:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      public final ConfigurableListableBeanFactory getBeanFactory() {
      synchronized(this.beanFactoryMonitor) {
      if (this.beanFactory == null) {
      throw new IllegalStateException("BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext");
      } else {
      return this.beanFactory;
      }
      }
      }

      他是返回的this.beanFactory,那么具体是什么呢?拉到定义,我们只在下图中找到赋值beanFactory的代码:

      那么也就是说,beanFacotryDefaultListableBeanFactory

    • 峰回路转,那我们直接到DefaultListableBeanFactory中看看getBeansOfType()方法的内部实现吧。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      @Override
      public <T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
      throws BeansException {
      String[] beanNames = getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
      Map<String, T> result = new LinkedHashMap<String, T>(beanNames.length);
      for (String beanName : beanNames) {
      try {
      result.put(beanName, getBean(beanName, type));
      }
      catch (BeanCreationException ex) {
      //异常处理代码忽略...
      }
      }
      return result;
      }

      上面的代码简单点就是做了下面几件事

      • 获取传入的类型的所有bean的名字,因为我们在保存解析后的配置时,同时也会保存它的beanName。
      • 循环遍历Bean的Name,然后调用getBean()方法通过beanName和Class获取对象。加入到Map中。注意,Map的key是BeanName。

    关于第二个问题,我们就扩展到这里了。给个结论吧,最后获取到的Map,key就是beanName,value就是对应的对象。也就是我们解析后的配置对象。

第二部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
//前面部分代码省略...前面部分就是从Spring容器中获取对应的类的所有bean
if (providerConfigMap != null && providerConfigMap.size() > 0) {
//我们假设providerConfigMap不为空,到这里又开始从Spring容器中获取ProtocolConfig对应的Bean
Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);
//如果ProtocolConfig不为空,也就是我们配置了<dubbo:protocol>标签,并成功解析
if (CollectionUtils.isEmptyMap(protocolConfigMap)
&& providerConfigMap.size() > 1) { // backward compatibility
List<ProviderConfig> providerConfigs = new ArrayList<ProviderConfig>();
//遍历providerConfigMap的value,加入到List中。
for (ProviderConfig config : providerConfigMap.values()) {
//只加入默认的
if (config.isDefault() != null && config.isDefault()) {
providerConfigs.add(config);
}
}
//如果list不为空,就调用setProviders
if (!providerConfigs.isEmpty()) {
setProviders(providerConfigs);
}
} else {
//如果我们ProtocolConfig是空的,就从providerConfigMap中提取出默认的ProviderConfig。
//如果有多个,就会报错。
ProviderConfig providerConfig = null;
for (ProviderConfig config : providerConfigMap.values()) {
if (config.isDefault() == null || config.isDefault()) {
if (providerConfig != null) {
throw new IllegalStateException("Duplicate provider configs: " + providerConfig + " and " + config);
}
providerConfig = config;
}
}
//设置provider
if (providerConfig != null) {
setProvider(providerConfig);
}
}
}

以上代码,唯一要单独说的就是setProviders()setProvider()方法。该方法在ServiceBean的父类ServiceConfig中,这个关联关系我们之前已经说过了。两个方法分别代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
@Deprecated  //注意,该方法已经过期了哦。
public void setProviders(List<ProviderConfig> providers) {
//调用convertProviderToProtocol把providerConfig转为ProtocolConfig。方法代码在下方。
this.protocols = convertProviderToProtocol(providers);
}

@Deprecated //注意这个方法也过期了
private static List<ProtocolConfig> convertProviderToProtocol(List<ProviderConfig> providers) {
if (CollectionUtils.isEmpty(providers)) {
return null;
}
//这里没得好说的,遍历list,调用convertProviderToProtocol()一个一个的转,然后放到List中
List<ProtocolConfig> protocols = new ArrayList<ProtocolConfig>(providers.size());
for (ProviderConfig provider : providers) {
//convertProviderToProtocol方法见下面
protocols.add(convertProviderToProtocol(provider));
}
return protocols;
}

@Deprecated //注意,该方法也过时了。
//可以看到,在里面就是new了个ProtocolConfig,然后手动赋值。
private static ProtocolConfig convertProviderToProtocol(ProviderConfig provider) {
ProtocolConfig protocol = new ProtocolConfig();
protocol.setName(provider.getProtocol().getName());
protocol.setServer(provider.getServer());
protocol.setClient(provider.getClient());
protocol.setCodec(provider.getCodec());
protocol.setHost(provider.getHost());
protocol.setPort(provider.getPort());
protocol.setPath(provider.getPath());
protocol.setPayload(provider.getPayload());
protocol.setThreads(provider.getThreads());
protocol.setParameters(provider.getParameters());
return protocol;
}

public void setProvider(ProviderConfig provider) {
//把providerConfig保存一份到ConfigMananger中。
ConfigManager.getInstance().addProvider(provider);
//给provider属性赋值。
this.provider = provider;
}

那么,这两个部分的代码合起来,无非就是做了如下几件事:

  • 从Spring容器中获取所有ProviderConfig类的对象,结果是一个Map。key是bean的名字,value就是bean对象。
  • 如果ProviderConfigMap不为空,则获取所有ProtocolConfig类的对象。
  • 如果有配多协议(ProtocolConfig对象不止一个),就把所有的ProviderConfig对象加入到List,并且调用setProviders()方法为ServiceConfig里面的protocols属性赋值。在内部,会把ProviderConfig转为ProtocolConfig
  • 如果没有配置多协议呢,就直接赋值给ServiceConfig里面的provider属性,如果有多个,就会报错。

注意,上面的都已经过时,在新版本中不推荐这样用了。这里是为了兼容旧版本

第二个if条件——设置ApplicationConfig

有了一个if条件的经验,我们就直接来看代码吧。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//一系列判断
if (getApplication() == null
&& (getProvider() == null || getProvider().getApplication() == null)) {
//这里不用说了,从Spring容器中获取所有ApplicationConfig类的对象.
//也就是<dubbo:application>标签对应的配置
Map<String, ApplicationConfig> applicationConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ApplicationConfig.class, false, false);
if (applicationConfigMap != null && applicationConfigMap.size() > 0) {
ApplicationConfig applicationConfig = null;
//遍历Map,如果有多个就会报错,一般我们在一个模块中只会配一个<dubbo:application>标签
for (ApplicationConfig config : applicationConfigMap.values()) {
if (applicationConfig != null) {
throw new IllegalStateException("Duplicate application configs: " + applicationConfig + " and " + config);
}
applicationConfig = config;
}
//保存ApplicationConfig到ServiceBean的父类ServiceConfig中。
//以便后续我们在ServiceBean中可以直接用到
if (applicationConfig != null) {
setApplication(applicationConfig);
}
}
}

这段代码毫无疑问,是从Spring中读取我们解析到的<dubbo:application>所对应的ApplicationConfig对象。然后保存到ServiceConfig中。简单吧。后面的if体,我就稍微注释下,不会再像现在这样了。下面我们看第三个if。

第三个if条件——设置ModuleConfig

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if (getModule() == null
&& (getProvider() == null || getProvider().getModule() == null)) {
Map<String, ModuleConfig> moduleConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ModuleConfig.class, false, false);
if (moduleConfigMap != null && moduleConfigMap.size() > 0) {
ModuleConfig moduleConfig = null;
for (ModuleConfig config : moduleConfigMap.values()) {
if (config.isDefault() == null || config.isDefault()) {
if (moduleConfig != null) {
throw new IllegalStateException("Duplicate module configs: " + moduleConfig + " and " + config);
}
moduleConfig = config;
}
}
if (moduleConfig != null) {
setModule(moduleConfig);
}
}
}

这段代码就不注释了,原因是因为和上面结构差不多,而且<dubbo:module>这个配置很少用。

第四个if条件——设置RegistryIds

1
2
3
4
5
6
7
8
9
10
if (StringUtils.isEmpty(getRegistryIds())) {
//从ApplicationConfig中取registryIds,或者从providerConfig中取。
//如果两个都有配,则以ProviderConfig为准
if (getApplication() != null && StringUtils.isNotEmpty(getApplication().getRegistryIds())) {
setRegistryIds(getApplication().getRegistryIds());
}
if (getProvider() != null && StringUtils.isNotEmpty(getProvider().getRegistryIds())) {
setRegistryIds(getProvider().getRegistryIds());
}
}

第五个if条件——设置注册中心配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
if ((CollectionUtils.isEmpty(getRegistries()))
&& (getProvider() == null || CollectionUtils.isEmpty(getProvider().getRegistries()))
&& (getApplication() == null || CollectionUtils.isEmpty(getApplication().getRegistries()))) {
//从Spring容器中取出所有的RegistryConfig,也就是配置的<dubbo:registry>,即注册中心的配置
Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false);
if (CollectionUtils.isNotEmptyMap(registryConfigMap)) {
List<RegistryConfig> registryConfigs = new ArrayList<>();
//如果registryIds不为空,就用","逗号切割下,然后在遍历结果。
//从registryConfigMap中通过id去获取对应的RegistryConfig
if (StringUtils.isNotEmpty(registryIds)) {
Arrays.stream(COMMA_SPLIT_PATTERN.split(registryIds)).forEach(id -> {
if (registryConfigMap.containsKey(id)) {
registryConfigs.add(registryConfigMap.get(id));
}
});
}
//如果registryIds是空,那么上面肯定是不会走了。那么我们配置的注册中心只能走下面的逻辑设置
if (registryConfigs.isEmpty()) {
//遍历map的value,直接放入到List中。
for (RegistryConfig config : registryConfigMap.values()) {
if (StringUtils.isEmpty(registryIds)) {
registryConfigs.add(config);
}
}
}
//保存注册中心到我们的ServiceConfig
if (!registryConfigs.isEmpty()) {
super.setRegistries(registryConfigs);
}
}
}

第六个if条件——设置元数据配置(新特性)

1
2
3
4
5
6
7
8
9
10
if (getMetadataReportConfig() == null) {
//获取MetaDataReportConfig
Map<String, MetadataReportConfig> metadataReportConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MetadataReportConfig.class, false, false);
if (metadataReportConfigMap != null && metadataReportConfigMap.size() == 1) {
//保存到ServiceConfig中
super.setMetadataReportConfig(metadataReportConfigMap.values().iterator().next());
} else if (metadataReportConfigMap != null && metadataReportConfigMap.size() > 1) {
throw new IllegalStateException("Multiple MetadataReport configs: " + metadataReportConfigMap);
}
}

第七个if条件——监控相关配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
if (getMonitor() == null
&& (getProvider() == null || getProvider().getMonitor() == null)
&& (getApplication() == null || getApplication().getMonitor() == null)) {
//从Spring容器中获取MonitorConfig
Map<String, MonitorConfig> monitorConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MonitorConfig.class, false, false);
if (monitorConfigMap != null && monitorConfigMap.size() > 0) {
MonitorConfig monitorConfig = null;
for (MonitorConfig config : monitorConfigMap.values()) {
if (config.isDefault() == null || config.isDefault()) {
//多个monitor配置会抛出异常
if (monitorConfig != null) {
throw new IllegalStateException("Duplicate monitor configs: " + monitorConfig + " and " + config);
}
monitorConfig = config;
}
}
//保存monitor到ServiceConfig中。
if (monitorConfig != null) {
setMonitor(monitorConfig);
}
}
}

第八个if条件——设置Metrics

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if (getMetrics() == null) {
//从Spring容器中获取MetricsConfig
Map<String, MetricsConfig> metricsConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MetricsConfig.class, false, false);
if (metricsConfigMap != null && metricsConfigMap.size() > 0) {
MetricsConfig metricsConfig = null;
for (MetricsConfig config : metricsConfigMap.values()) {
//多个配置抛异常
if (metricsConfig != null) {
throw new IllegalStateException("Duplicate metrics configs: " + metricsConfig + " and " + config);
}
metricsConfig = config;
}
if (metricsConfig != null) {
setMetrics(metricsConfig);
}
}
}

第九个if条件——设置ProtocolIds

1
2
3
4
5
if (StringUtils.isEmpty(getProtocolIds())) {
if (getProvider() != null && StringUtils.isNotEmpty(getProvider().getProtocolIds())) {
setProtocolIds(getProvider().getProtocolIds());
}
}

第十个if条件——保存协议信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
if (CollectionUtils.isEmpty(getProtocols())
&& (getProvider() == null || CollectionUtils.isEmpty(getProvider().getProtocols()))) {
//从Spring中获取ProtocolConfig。也就是<dubbo:protocol>标签。
Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);
if (protocolConfigMap != null && protocolConfigMap.size() > 0) {
List<ProtocolConfig> protocolConfigs = new ArrayList<ProtocolConfig>();
//如果ProtocolIds不为空,就用“,”逗号切割,遍历结果,从Map中取出对应的ProtocolConfig,放到List中
if (StringUtils.isNotEmpty(getProtocolIds())) {
Arrays.stream(COMMA_SPLIT_PATTERN.split(getProtocolIds()))
.forEach(id -> {
if (protocolConfigMap.containsKey(id)) {
protocolConfigs.add(protocolConfigMap.get(id));
}
});
}
//上面如果没有设置值,则走下面的逻辑,直接把ProtocolConfig加入到List
if (protocolConfigs.isEmpty()) {
for (ProtocolConfig config : protocolConfigMap.values()) {
if (StringUtils.isEmpty(protocolIds)) {
protocolConfigs.add(config);
}
}
}
//保存到ServiceBean中
if (!protocolConfigs.isEmpty()) {
super.setProtocols(protocolConfigs);
}
}
}

第十一个if条件——保存path

1
2
3
4
5
6
7
8
if (StringUtils.isEmpty(getPath())) {
//这里的beanName就是我们在<dubbo:service>的interface属性值
if (StringUtils.isNotEmpty(beanName)
&& StringUtils.isNotEmpty(getInterface())
&& beanName.startsWith(getInterface())) {
setPath(beanName);
}
}

最后一个if——导出

1
2
3
4
if (!supportedApplicationListener) {
//主要的逻辑都在这个里面了。
export();
}

总结

这一篇有点不尽人意。总体意识很简单,就是从Spring容器中把我们上一篇解析的出来的配置,保存到ServiceConfig中,后面我们开始真正进入服务导出的内容了,我们一起期待。

对了,那我们<dubbo:service>标签的配置是怎么放到ServiceConfig中的呢?在上一篇中,我们是直接把配置就已经解析好了的,也就是说ServiceBean中在执行afterPropertiesSet()方法前,就已经把<dubbo:service>的配置保存了,而这里只是保存下其他的标签的配置到ServiceBean,说白点就是为ServiceBean的一些需要的属性赋值,以便后续导出服务时使用。

这篇可能写的不怎么好,没得状态。谢谢大佬们的观看,下一篇再见~


评论