5-dubbo源码:启动服务前服务配置ServiceConfig类型是如何初始化的

public static void startWithBootstrap() {
        ServiceConfig<DemoServiceImpl> service = new ServiceConfig<>();
        service.setInterface(DemoService.class);
        service.setRef(new DemoServiceImpl());
        DubboBootstrap bootstrap = DubboBootstrap.getInstance();
        bootstrap.application(new ApplicationConfig("dubbo-demo-api-provider"))
                .registry(new RegistryConfig("zookeeper://127.0.0.1:2181"))
                .protocol(new ProtocolConfig(CommonConstants.DUBBO, -1))
               
        
                .start()
                .await();

}

ServiceConfig service = new ServiceConfig<>();

继承关系图:
在这里插入图片描述

继承关系图自己一个带有说明

在这里插入图片描述

  • AbstractConfig,抽象的配置类型,也是最顶层的服务配置类型,封装着解析配置的实用方法和公共方法,比如服务id的设置,服务标签名字的处理,服务参数的添加,属性的提取等等 比如配置解析 appendParameters()方法:根据类上所有公有方法的@Parameter注解从配置信息获取配置并通过setXXX方法填充 appendAttributes()方法:根据类上所有公有方法的@Parameter注解从配置信息获取配置存放到map集合中 比如校验 checkExtension()方法:检查属性的长度和非法字符串

  • AbstractMethodConfig,抽象的方法配置,同样这个类型也是见名知意,服务方法的相关配置处理, 这个类型主要用于对服务方法的一些配置信息建模比如服务方法的调用超时时间,重试次数,最大并发调用数,负载均衡策略,是否异步调用,是否确认异步发送等等配置信息.

  • AbstractInterfaceConfig,抽象的接口配置,与前面介绍的方法配置类似, 这个类型是对服务接口的建模,主要的配置信息有暴漏服务的接口名字,服务接口的版本号,客户/提供方将引用的远程服务分组,服务元数据,服务接口的本地impl类名,服务监控配置, 对于生成动态代理的策略,可以选择两种策略:jdk和javassist,容错类型等等配置.

  • =============上面是消费方和提供方公共配置,下面是服务方独有的配置=================

  • AbstractServiceConfig,抽象的服务配置,这个就与我们的服务提供者有了具体的关系了,主要记录了一些服务提供者的公共配置,如服务版本,服务分组,服务延迟注册毫秒数,是否暴漏服务,服务权重,是否为动态服务,服务协议类型,是否注册等等.

  • ServiceConfigBase,服务的基础配置类,这个类型仍旧是个抽象的类型提取了一些基础的配置:导出服务的接口类,服务名称,接口实现的引用类型,提供者配置,是否是通用服务GenericService

  • ServiceConfig,服务配置实现类, 上面的类型都是抽象类型不能做为具体存在的事物,这个类型是我们出现的第一个服务配置实现类型,服务配置实现类已经从父类型中继承了这么多的属性,这里主要为实现服务提供了一些配置如服务的协议配置,服务的代理工厂JavassistProxyFactory是将生成导出服务代理的ProxyFactory实现,是其默认实现,服务提供者模型,是否导出服务,导出的服务列表,服务监听器等等.

  • =============其他=================

    1. ModubleConfig 模块信息

      我们可以针对一个应用区分不同模块,并为模块设置不同的配置信息 比如注册信息,协议信息等

    2. ProviderConfig 服务提供者全局配置

    3. RegistryConfig 注册相关配置,dubbo目前支持的注册中心有五种分别为:

       (1)、Zookeeper (2)、Multicast (3)、Redis (4)、Simple
      
    4. MonitorConfig 监控中心配置

    5. ProtocolConfig dubbo服务请求协议

      dubbo消费协议如下:  ①dubbo://、②hessian://、③rmi://、 ④http://、⑤webservice://、⑦memcached://、⑧redis://
      
    6. ProviderConfig 服务提供者全局配置

    ServiceConfig构造器的初始化调用链

    我现在用的3.2最新版本,4-beta版本,代码是最新的,你如果不是最新的可能代码不一样,原来对Model的初始化就在构造方法中完成的,我这个版本对model的初始化就没有,直接放在了 bootstrap.service(service),因此构造方法中就没太多可以分析

    根据Java基础的构造器知识,在每个构造器的第一行都会有个super方法来调用父类的构造器,当前这个super方法我们可以不写但是Java编译器底层还是会为我们默认加上这么一行super()代码来调用父类构造器的.

    这个地方代码可能不太一样,我目前用的最新的代码创建对象的时候 没有对ScopeModel相关处理,反而放到
    boostrap.service(service)
    初始化就不再分析,比较简单

    在ServiceConfigBase类中创建了一个 ServiceMetadata 原数据

    
        public ServiceConfigBase() {
            serviceMetadata = new ServiceMetadata();
            serviceMetadata.addAttribute("ORIGIN_CONFIG", this);
        }
    

    bootstrap.service(service)

    DubboBootstrap bootstrap = DubboBootstrap.getInstance();
    

    获取实例的时候

    public static DubboBootstrap getInstance() {
            if (instance == null) {
                synchronized (DubboBootstrap.class) {
                    if (instance == null) {
                        instance = DubboBootstrap.getInstance(ApplicationModel.defaultModel());
                    }
                }
            }
            return instance;
        }
        public static DubboBootstrap getInstance(ApplicationModel applicationModel) {
            return ConcurrentHashMapUtils.computeIfAbsent(instanceMap, applicationModel, _k -> new DubboBootstrap(applicationModel));
        }
    

    org.apache.dubbo.rpc.model.ApplicationModel#defaultModel

     public static ApplicationModel defaultModel() {
            // should get from default FrameworkModel, avoid out of sync
            return FrameworkModel.defaultModel().defaultApplication();
        }
    

    this.applicationModel = ApplicationModel.defaultModel()

    booststrap.service(service) 时候

    applicationModel.getDefaultModule() 上面是代码的精简: 相当于:
    ApplicationModel.defaultModel().getDefaultModule()

    从上面的代码看绕来绕去的我们写一些简写的代码

    DubboBootstrap bootstrap = DubboBootstrap.getInstance();
    

    相当于下面的一行代码:

    Model的相关内容这里先不分析, 参考 《3-dubbo框架,应用程序,模块领域模型Model对象的初始化》

    new DubboBootstrap(FrameworkModel.defaultModel().defaultApplication())
    
    
    private DubboBootstrap(ApplicationModel applicationModel) {
    		//注入一个ApplicationModel
            this.applicationModel = applicationModel;
            configManager = applicationModel.getApplicationConfigManager();
            environment = applicationModel.getModelEnvironment();
    
            executorRepository = ExecutorRepository.getInstance(applicationModel);
            applicationDeployer = applicationModel.getDeployer();
            // listen deploy events
            applicationDeployer.addDeployListener(new DeployListenerAdapter<ApplicationModel>() {
                @Override
                public void onStarted(ApplicationModel scopeModel) {
                    notifyStarted(applicationModel);
                }
    
                @Override
                public void onStopped(ApplicationModel scopeModel) {
                    notifyStopped(applicationModel);
                }
    
                @Override
                public void onFailure(ApplicationModel scopeModel, Throwable cause) {
                    notifyStopped(applicationModel);
                }
            });
            // register DubboBootstrap bean
            applicationModel.getBeanFactory().registerBean(this);
        }
    

    创建一个模块模型对象ModuleModel关于模型对象的细节我们会在下个章节来说,这里我们继续来看调用链
    这个时候就把ScopeModel 相关初始化完成, 这里面内容比较多后面一个专题分析

    public DubboBootstrap service(ServiceConfig<?> serviceConfig, ModuleModel moduleModel) {
            serviceConfig.setScopeModel(moduleModel);
            moduleModel.getConfigManager().addService(serviceConfig);
            return this;
        }
    
    public final void setScopeModel(ScopeModel scopeModel) {
            if (scopeModel != null && this.scopeModel != scopeModel) {
                checkScopeModel(scopeModel);
                ScopeModel oldScopeModel = this.scopeModel;
                this.scopeModel = scopeModel;
                // reinitialize spi extension and change referenced config's scope model
                //被子类重写的方法,根据多态会调用具体子类型的这个方法我们下面来看
                //子类应该重写此方法以初始化其SPI扩展并更改引用的配置的范围模型。
                this.postProcessAfterScopeModelChanged(oldScopeModel, this.scopeModel);
            }
        }
    

    重写的postProcessAfterScopeModelChanged调用逻辑
    当ScopeModel模型对象发生了改变,上面调用了postProcessAfterScopeModelChanged方法来通知模型对象改变的时候要执行的操作,根据多态重写的逻辑我们从实现类的postProcessAfterScopeModelChanged来看,在下面的调用链路中部分父类型并未实现postProcessAfterScopeModelChanged方法我们就直接忽略了
    第一个被调用到的是ServiceConfig类型的postProcessAfterScopeModelChanged方法

    @Override
        protected void postProcessAfterScopeModelChanged(ScopeModel oldScopeModel, ScopeModel newScopeModel) {
            super.postProcessAfterScopeModelChanged(oldScopeModel, newScopeModel);
            //初始化当前协议对象,通过扩展机制获取协议Protocol类型的对象
            protocolSPI = this.getExtensionLoader(Protocol.class).getAdaptiveExtension();
            //初始化当前代理工厂对象,通过扩展机制获取ProxyFactory类型的对象
            proxyFactory = this.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
        }
    

    第二个被调用到的方法为ServiceConfigBase的postProcessAfterScopeModelChanged方法

    @Override
        protected void postProcessAfterScopeModelChanged(ScopeModel oldScopeModel, ScopeModel newScopeModel) {
            super.postProcessAfterScopeModelChanged(oldScopeModel, newScopeModel);
            //当服务提供者配置对象不为空时候为服务提供者对象设置域模型,这里服务提供者对象仍旧为空,这个一般用在兼容Dubbo低版本
            if (this.consumer != null && this.consumer.getScopeModel() != getScopeModel()) {
                this.consumer.setScopeModel(getScopeModel());
            }
        }
    

    第三个被调用到的是AbstractInterfaceConfig类型的postProcessAfterScopeModelChanged方法

     @Override
        protected void postProcessAfterScopeModelChanged(ScopeModel oldScopeModel, ScopeModel newScopeModel) {
            //当前版本的父类已经没有逻辑,这里是最后一个调用 因为父类没做处理
            super.postProcessAfterScopeModelChanged(oldScopeModel, newScopeModel);
            // change referenced config's scope model
            //获取应用程序模型对象 没设置的情况是默认
            ApplicationModel applicationModel = ScopeModelUtil.getApplicationModel(getScopeModel());
            //为配置中心对象设置ApplicationModel类型对象(当前阶段配置中心配置对象为空)
            if (this.configCenter != null && this.configCenter.getScopeModel() != applicationModel) {
                this.configCenter.setScopeModel(applicationModel);
            }
            //为元数据配置对象设置ApplicationModel类型对象(当前阶段数据配置配置对象为空)
            if (this.metadataReportConfig != null && this.metadataReportConfig.getScopeModel() != applicationModel) {
                this.metadataReportConfig.setScopeModel(applicationModel);
            }
            //为MonitorConfig服务监控配置对象设置ApplicationModel类型对象(当前阶段数据配置配置对象为空)
            if (this.monitor != null && this.monitor.getScopeModel() != applicationModel) {
                this.monitor.setScopeModel(applicationModel);
            }
            //如果注册中心配置列表不为空则为每个注册中心配置设置一个ApplicationModel类型对象(当前注册中心对象都为空)
            if (CollectionUtils.isNotEmpty(this.registries)) {
                this.registries.forEach(registryConfig -> {
                    if (registryConfig.getScopeModel() != applicationModel) {
                        registryConfig.setScopeModel(applicationModel);
                    }
                });
            }
        }
    

    ServiceConfigBase构造器的初始化

    public ServiceConfigBase() {
            //服务元数据对象创建
            serviceMetadata = new ServiceMetadata();
            //为服务元数据对象
            serviceMetadata.addAttribute("ORIGIN_CONFIG", this);
        }
    

    注意, ServiceMetadata这个类目前在Dubbo中没有用法。与服务级别相关的数据,例如名称、版本、业务服务的类加载器、安全信息等,还带有用于扩展的AttributeMap。

    服务配置对象的创建过程就这样结束了,当然有一些细节会放到后面来写上面主要顺序是按照代码执行的顺序来写的部分地方可能稍微做了调整,如果有条件的同学一定要自己进行DEBUG了解下细节

    属性信息的说明

    属性类型是否必填缺省值作用描述
    interfaceclassT服务发现服务接口名
    refobjectT服务发现服务对象实现引用
    versionstringF0.0.0服务发现服务版本,建议两位数字版本,如:1.0,通常在接口不兼容时版本号才需要升级
    groupstringF服务发现服务分组,当一个接口有多个实现,可以用分组区分
    delayintF0性能调优延迟注册服务时间(毫秒) ,设为-1时,表示延迟到Spring容器初始化完成时暴露服务
    timeoutintF1000性能调优远程服务调用超时时间(毫秒)
    retriesintF2性能调优远程服务调用重试次数,不包括第一次调用,不需要重试请设为0
    loadbalancestringFrandom性能调优负载均衡策略,可选值:random,roundrobin,leastactive,分别表示:随机,轮询,最少活跃调用
    asyncbooleanFfalse性能调优是否缺省异步执行,不可靠异步,只是忽略返回值,不阻塞执行线程
    stubclass/booleanFfalse服务治理设为true,表示使用缺省代理类名,即:接口名 + Stub后缀,服务接口客户端本地代理类名,用于在客户端执行本地逻辑,如本地缓存等,该本地代理类的构造函数必须允许传入远程代理对象
    mockclass/booleanFfalse服务治理设为true,表示使用缺省Mock类名,即:接口名 + Mock后缀,服务接口调用失败Mock实现类,该Mock类必须有一个无参构造函数,与Local的区别在于,Local总是被执行,而Mock只在出现非业务异常(比如超时,网络异常等)时执行,Local在远程调用之前执行,Mock在远程调用后执行。
    tokenstring/booleanFfalse服务治理令牌验证,为空表示不开启,如果为true,表示随机生成动态令牌,否则使用静态令牌,令牌的作用是防止消费者绕过注册中心直接访问,保证注册中心的授权功能有效,如果使用点对点调用,需关闭令牌功能
    registrystringF缺省向所有registry注册配置关联向指定注册中心注册,在多个注册中心时使用,值为dubbo:registry的id属性,多个注册中心ID用逗号分隔,如果不想将该服务注册到任何registry,可将值设为N/A
    providerstringF缺省使用第一个provider配置配置关联指定provider,值为dubbo:provider的id属性
    deprecatedbooleanFfalse服务治理服务是否过时,如果设为true,消费方引用时将打印服务过时警告error日志
    dynamicbooleanFtrue服务治理服务是否动态注册,如果设为false,注册后将显示后disable状态,需人工启用,并且服务提供者停止时,也不会自动取消册,需人工禁用。
    accesslogstring/booleanFfalse服务治理设为true,将向logger中输出访问日志,也可填写访问日志文件路径,直接把访问日志输出到指定文件
    ownerstringFfalse服务治理服务负责人,用于服务治理,请填写负责人公司邮箱前缀
    weightintF性能调优服务权重
    executesintF0性能调优服务提供者每服务每方法最大可并行执行请求数
    proxystringFjavassist性能调优生成动态代理方式,
    clusterstringFfailover性能调优集群方式
    filterstringFdefault性能调优服务提供方远程调用过程拦截器名称,多个名称用逗号分隔 2.0.5以上版本
    listenerstringFdefault性能调优服务提供方导出服务监听器名称,多个名称用逗号分隔
    protocolstringF配置关联使用指定的协议暴露服务,在多协议时使用,值为dubbo:protocol的id属性,多个协议ID用逗号分隔
    registerbooleanFtrue服务治理该协议的服务是否注册到注册中心
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值