2.源码分析

服务导出的入口方法是 ServiceBean 的 onApplicationEvent。onApplicationEvent 是一个事件响应方法,该方法会在收到 Spring 上下文刷新事件后执行服务导出操作。方法代码如下:

  1. public void onApplicationEvent(ContextRefreshedEvent event) {
  2. // 是否有延迟导出 && 是否已导出 && 是不是已被取消导出
  3. if (isDelay() && !isExported() && !isUnexported()) {
  4. // 导出服务
  5. export();
  6. }
  7. }

这个方法首先会根据条件决定是否导出服务,比如有些服务设置了延时导出,那么此时就不应该在此处导出。还有一些服务已经被导出了,或者当前服务被取消导出了,此时也不能再次导出相关服务。注意这里的 isDelay 方法,这个方法字面意思是“是否延迟导出服务”,返回 true 表示延迟导出,false 表示不延迟导出。但是该方法真实意思却并非如此,当方法返回 true 时,表示无需延迟导出。返回 false 时,表示需要延迟导出。与字面意思恰恰相反,这个需要大家注意一下。下面我们来看一下这个方法的逻辑。

  1. // -☆- ServiceBean
  2. private boolean isDelay() {
  3. // 获取 delay
  4. Integer delay = getDelay();
  5. ProviderConfig provider = getProvider();
  6. if (delay == null && provider != null) {
  7. // 如果前面获取的 delay 为空,这里继续获取
  8. delay = provider.getDelay();
  9. }
  10. // 判断 delay 是否为空,或者等于 -1
  11. return supportedApplicationListener && (delay == null || delay == -1);
  12. }

暂时忽略 supportedApplicationListener 这个条件,当 delay 为空,或者等于-1时,该方法返回 true,而不是 false。这个方法的返回值让人有点困惑。该方法目前已被重构,详细请参考 dubbo #2686

现在解释一下 supportedApplicationListener 变量含义,该变量用于表示当前的 Spring 容器是否支持 ApplicationListener,这个值初始为 false。在 Spring 容器将自己设置到 ServiceBean 中时,ServiceBean 的 setApplicationContext 方法会检测 Spring 容器是否支持 ApplicationListener。若支持,则将 supportedApplicationListener 置为 true。ServiceBean 是 Dubbo 与 Spring 框架进行整合的关键,可以看做是两个框架之间的桥梁。具有同样作用的类还有 ReferenceBean。

现在我们知道了 Dubbo 服务导出过程的起点,接下来对服务导出的前置逻辑进行分析。