8-Dubbo启动器DubboBootstrap借助双重校验锁的单例模式进行对象的初始化

8.1 启动器简介

在说启动器之前先把视野拉回第一章《1-从一个服务提供者的Demo说起》我们的Demo代码,下面只贴一下核心代码:

  1. public class Application {
  2. public static void main(String[] args) throws Exception {
  3. startWithBootstrap();
  4. }
  5. private static void startWithBootstrap() {
  6. //前面的文章都在说这个服务配置对象的创建,中间又说了分层域模型,扩展加载机制
  7. ServiceConfig<DemoServiceImpl> service = new ServiceConfig<>();
  8. //为服务配置下服务接口和服务实现,下面两行用来初始化对象就不详细说了
  9. service.setInterface(DemoService.class);
  10. service.setRef(new DemoServiceImpl());
  11. //这一个篇章主要说这里:
  12. DubboBootstrap bootstrap = DubboBootstrap.getInstance();
  13. bootstrap.application(new ApplicationConfig("dubbo-demo-api-provider"))
  14. .registry(new RegistryConfig("zookeeper://127.0.0.1:2181"))
  15. .protocol(new ProtocolConfig(CommonConstants.DUBBO, -1))
  16. .service(service)
  17. .start()
  18. .await();
  19. }
  20. }

Dubbo3 往云原生的方向走自然要针对云原生应用的应用启动,应用运行,应用发布等信息做一些建模,这个DubboBootstrap就是用来启动Dubbo服务的.类似于Netty的Bootstrap类型和ServerBootstrap启动器

8.2 双重校验锁的单例模式创建启动器对象的

Dubbo的bootstrap类为啥要用单例模式:

通过调用静态方法getInstance()获取单例实例。之所以设计为单例,是因为Dubbo中的一些类(如ExtensionLoader)只为每个进程设计一个实例。

下面就来直接看代码吧,代码胜千言:
对象的调用代码如下:

  1. DubboBootstrap bootstrap = DubboBootstrap.getInstance();

DubboBootstrap获取对象的getInstance()方法:

  1. public static DubboBootstrap getInstance() {
  2. //双重校验锁第一次判断空
  3. if (instance == null) {
  4. //为空都进行排队
  5. synchronized (DubboBootstrap.class) {
  6. //双重校验锁第二次判断空 上面为空的都排队了这里得判断下
  7. if (instance == null) {
  8. //调用重载方法获取对象
  9. instance = DubboBootstrap.getInstance(ApplicationModel.defaultModel());
  10. }
  11. }
  12. }
  13. return instance;
  14. }

DubboBootstrap获取对象重载的getInstance(ApplicationModel applicationModel)方法:

computeIfAbsent() 方法对 hashMap 中指定 key 的值进行重新计算,如果不存在这个 key,则添加到 hashMap 中。

instanceMap设计为Map<ApplicationModel, DubboBootstrap>类型 Key,意味着可以为多个应用程序模型创建不同的启动器,启动多个服务

  1. public static DubboBootstrap getInstance(ApplicationModel applicationModel) {
  2. return instanceMap.computeIfAbsent(applicationModel, _k -> new DubboBootstrap(applicationModel));
  3. }

8.3 DubboBootstrap的构造器代码

构造器代码是逻辑比较复杂的地方,我们先来看下代码

  1. private DubboBootstrap(ApplicationModel applicationModel) {
  2. //存储应用程序启动模型
  3. this.applicationModel = applicationModel;
  4. //获取配置管理器ConfigManager: 配置管理器的扩展类型ApplicationExt ,扩展名字config
  5. configManager = applicationModel.getApplicationConfigManager();
  6. //获取环境信息Environment: 环境信息的扩展类型为ApplicationExt,扩展名字为environment
  7. environment = applicationModel.getModelEnvironment();
  8. //执行器存储仓库(线程池)ExecutorRepository: 扩展类型为ExecutorRepository,默认扩展扩展名字为default
  9. executorRepository = applicationModel.getExtensionLoader(ExecutorRepository.class).getDefaultExtension();
  10. //初始化并启动应用程序实例ApplicationDeployer,DefaultApplicationDeployer类型
  11. applicationDeployer = applicationModel.getDeployer();
  12. // listen deploy events
  13. //为发布器 设置生命周期回调
  14. applicationDeployer.addDeployListener(new DeployListenerAdapter<ApplicationModel>() {
  15. @Override
  16. public void onStarted(ApplicationModel scopeModel) {
  17. notifyStarted(applicationModel);
  18. }
  19. @Override
  20. public void onStopped(ApplicationModel scopeModel) {
  21. notifyStopped(applicationModel);
  22. }
  23. @Override
  24. public void onFailure(ApplicationModel scopeModel, Throwable cause) {
  25. notifyStopped(applicationModel);
  26. }
  27. });
  28. //将启动器对象注册到应用程序模型applicationModel的Bean工厂中
  29. // register DubboBootstrap bean
  30. applicationModel.getBeanFactory().registerBean(this);
  31. }

技术咨询支持,可以扫描微信公众号进行回复咨询
在这里插入图片描述