Spring IoC容器启动完成之后就应该开始dubbo的初始化工作了.

DubboBootstrapApplicationListener

既然是在基于spring,那么启动的引导就那几个花样,dubbo使用的是实现ApplicationListener接口的方式(注意是2.7.6,其他版本可能不一样).

先看构造方法: 在DubboBootstrapApplicationListener的构造方法中,只做了一件事,就是初始化DubboBootstrap,调用的是DubboBootstrap.getInstance(),这个getInstance里是经典的两次判空实现单例,略过不谈.

OneTimeExecutionApplicationContextEventListener实现了ApplicationListener,提供了抽象方法onApplicationContextEvent来处理spring的事件.

DubboBootstrapApplicationListener是OneTimeExecutionApplicationContextEventListener的一个子类,onApplicationContextEvent的具体逻辑就是在这里实现的.

onApplicationContextEvent

可以看到onApplicationContextEvent中处理了两种事件,ContextRefreshedEvent和ContextClosedEvent,分别对应onContextRefreshedEvent方法和onContextClosedEvent方法.

onContextRefreshedEvent方法和onContextClosedEvent方法的具体逻辑也比较简单,就是调用了DubboBootstrap的start和stop方法.

DubboBootstrap

上边说了半天,其实就是dubbo启动的引导,也就是调用dubbo的启动入口,DubboBootstrap才是真正的启动实现,真正复杂的也在这里边.

还是先看构造方法,做了下边几件事:

  1. 初始化了一个 ConfigManager ❶
  2. 初始化了一个 Environment ❷
  3. 注册了一个DubboShutdownHook,shutdown的时候调用DubboBootstrap的destroy()方法

start()

上边说了,启动收到ContextRefreshedEvent事件的时候启动dubbo,启动就是执行这个方法,这才是dubbo启动的核心入口.

这里边做了几件事:

  1. initialize(); 看起来像是初始化的一些逻辑,一会深究
  2. exportServices(); 看起来像是注册Provider的入口 ❸
  3. exportMetadataService(); registerServiceInstance(); 2.7.8之后才有的逻辑,先跳过,不影响主逻辑
  4. referServices(); 看起来像是注入consumer的bean ❹
  5. awaitFinish(); 等待asyncExportingFutures初始化完成,这个看起来也不影响主逻辑的理解,先跳过吧.

initialize()

这里边做了几件事:

  1. ApplicationModel.initFrameworkExts(); 初始化所有FrameworkExt,其实就是SPI形式的Lifecycle
  2. startConfigCenter(); dubbo的配置中心模块,后续我们深入研究 ❺
  3. loadRemoteConfigs();
  4. checkGlobalConfigs();
  5. startMetadataCenter();
  6. initMetadataService();
  7. initMetadataServiceExports();
  8. initEventListener();

至此其实dubbo启动的主逻辑就差不多了,剩下的就是丰富里边的细节了.

TODO

留几个flag,后面一个一个啃

❶ ConfigManager初始化的时候用到了Extension逻辑,其实就是dubbo的SPI机制,这块比较复杂之后详细研究
❷ 和❶一样
❸ Provider的注册逻辑,比较复杂后续展开说
❹ Consumer的注入逻辑,比较复杂后续展开说
❺ 看起来SPI机制了解了之后就得研究配置模块了