本文基于dubbo 2.7.5版本代码


DubboBootstrap在dubbo中的作用

  • ConfigManager
  • Environment


DubboBootstrap主要处理dubbo所有的配置信息,功能主要有:

  1. 持有ConfigManager、Environment对象并且对其初始化,这两个对象都是与配置相关的;
  2. 更新配置中心配置对象ConfigCenterConfig的属性值;
  3. 加载元数据中心对象;
  4. 检查各个配置对象的属性值是否合法;
  5. 注册java的关闭钩子;
  6. 服务端服务的暴露。

该对象在一个dubbo实例中只能有一个,通过静态方法getInstance获取。getInstance方法调用DubboBootstrap的无参构造方法,在无参构造方法中创建了ConfigManager、Environment对象,之后将DubboShutdownHook关闭钩子注册到java中。

ConfigManager

ConfigManager存储了所有dubbo的配置对象:RegistryConfig、ConsumerConfig、ModuleConfig、ProtocolConfig、ProviderConfig、ApplicationConfig、MonitorConfig。
类似于一个本地的配置中心,如果要查询配置信息,访问ConfigManager获取对应的配置对象即可,任何配置对象修改了,都要刷新ConfigManager,比如ApplicationConfig修改了属性值,便会调用refreshAll方法修改ConfigManager。
这些配置对象都存储在该对象的属性configsCache中,该属性是一个HashMap对象,因为HashMap不是线程安全的,所以提供了属性lock(ReadWriteLock对象)对访问属性configsCache的操作加锁。
ConfigManager提供了大量的setXXX和addXXX方法,这些方法最终都是调用addConfig方法,addConfig方法将配置对象添加到属性configsCache中。
属性configsCache的类型是Map<String, Map<String, AbstractConfig>>,是一个两层Map结构,第一层的key是配置类名字的变体,比如调用addMetadataReports增加MetadataReportConfig对象,那么第一层的key是metadata-report,也就是将类名字的Config去掉,然后在类名字中大写字母前加“-”,最后将所有的大写字母变为小写字母。第二层的key是配置对象中的id属性的值,如果没有设置id值,默认使用类名字+“#default”作为key。
在dubbo中,一般访问ConfigManager,是使用ApplicationModel.getConfigManager()通过SPI获取对象的。
因为AbstractConfig的addIntoConfigManager方法有注解@PostConstruct,因此在AbstractConfig对象创建完毕后,spring会自动调用addIntoConfigManager方法,在该方法中将配置对象添加到ConfigManager中。通过addIntoConfigManager方法保证了所有的配置对象都会存储到ConfigManager中。
DubboBootstrap也提供了大量的方法用于向ConfigManager中添加配置对象以及从ConfigManager中获取配置对象。

Environment

Environment也是存储配置信息,与ConfigManager不同的是,Environment主要处理的与系统配置相关,比如Java系统配置,以及配置中心的配置。
获取Environment对象,是通过ApplicationModel.getEnvironment()得到。

DubboBootstrap的initialize方法是初始化方法,是DubboBootstrap最重要的方法,通过对这个方法的分析,可以了解该类的具体作用。该方法有两个调用位置:

  1. 在ReferenceConfig的init方法(客户端启动)中执行;
  2. 在服务端启动的时候,当spring发布了ContextRefreshedEvent事件后,会触发监听器DubboBootstrapApplicationListener,该监听器也会调用initialize方法。

其他的调用位置也有,但是上述两个位置分别是客户端和服务端启动时第一次调用的位置,因此后续其他调用会跳过initialize方法。
在下一篇文章中,将详细介绍initialize()方法里面各个方法的作用。

private void initialize() {
	if (!initialized.compareAndSet(false, true)) {
		return;//initialize方法只能初始化一次
	}
	ApplicationModel.iniFrameworkExts();//初始化FrameworkExt实现类,Environment是FrameworkExt实现类,这里会调用Environment的initialize方法
	startConfigCenter();//
	useRegistryAsConfigCenterIfNecessary();//
	startMetadataReport();//
	loadRemoteConfigs();//
	checkGlobalConfigs();//
	initMetadataService();//
	initMetadataServiceExporter();//
	initEventListener();//
	if (logger.isInfoEnabled()) {
		logger.info(NAME + " has been initialized!");
	}
}