2 ServiceConfig对象的建模
上面这几行代码虽然看似简单,仅仅几行的启动,但是完全掌握也得下一翻大功夫,接下来我们重点看启动代码中的第一行,创建一个服务配置对象:
下面是一个简单的UML继承关系图,当然这个图很是简单的,这里仅仅列出了当前服务提供者的相关服务配置继承关系, 服务提供者独有的配置标注颜色为蓝色,一些可能与服务引用配置所共有的父类型我们用红色背景,当然这里为了简便起见不会提起服务引用相关的配置类型,这里列举了如下服务提供者类型,他们各司其职:
图2.1 服务引用类继承关系UML
- AbstractConfig
- 抽象的配置类型,也是最顶层的服务配置类型,封装着解析配置的实用方法和公共方法,比如服务id的设置,服务标签名字的处理,服务参数的添加,属性的提取等等
AbstractMethodConfig
**抽象的方法配置**,同样这个类型也是见名知意,服务方法的相关配置处理,这个类型主要用于对服务方法的一些配置信息建模比如服务方法的调用超时时间,重试次数,最大并发调用数,负载均衡策略,是否异步调用,是否确认异步发送等等配置信息.
AbstractInterfaceConfig
- 抽象的接口配置,与前面介绍的方法配置类似,这个类型是对服务接口的建模,主要的配置信息有暴漏服务的接口名字,服务接口的版本号,客户/提供方将引用的远程服务分组,服务元数据,服务接口的本地impl类名,服务监控配置,对于生成动态代理的策略,可以选择两种策略:jdk和javassist,容错类型等等配置
- AbstractServiceConfig
- 抽象的服务配置,这个就与我们的服务提供者有了具体的关系了,主要记录了一些服务提供者的公共配置,如服务版本,服务分组,服务延迟注册毫秒数,是否暴漏服务,服务权重,是否为动态服务,服务协议类型,是否注册等等. - ServiceConfigBase
- 服务的基础配置类,这个类型仍旧是个抽象的类型提取了一些基础的配置:导出服务的接口类,服务名称,接口实现的引用类型,提供者配置,是否是通用服务GenericService - ServiceConfig
- 服务配置实现类, 上面的类型都是抽象类型不能做为具体存在的事物,这个类型是我们出现的第一个服务配置实现类型,服务配置实现类已经从父类型中继承了这么多的属性,这里主要为实现服务提供了一些配置如服务的协议配置,服务的代理工厂JavassistProxyFactory是将生成导出服务代理的ProxyFactory实现,是其默认实现,服务提供者模型,是否导出服务,导出的服务列表,服务监听器等等. - ServiceBean
- 服务工厂Bean ,这个主要是Spring模块来简化配置的一个服务工厂Bean这里就先不详细介绍Spring相关的配置. -
有了上面的类型继承关系我们就比较好分析了,接下来我们开始创建服务配置对象如下代码所示:
ServiceConfig<DemoServiceImpl> service = new ServiceConfig<>();
根据Java基础的构造器知识,在每个构造器的第一行都会有个super方法来调用父类的构造器,当前这个super方法我们可以不写但是Java编译器底层还是会为我们默认加上这么一行super()代码来调用父类构造器的.
根据super调用链这里先来看AbstractMethodConfig抽象方法配置
在这个构造器中只有个super方法用来调用父类型的构造器,但是在调用之前会先使用代码 ApplicationModel.defaultModel().getDefaultModule() 创建一个模块模型对象ModuleModel
关于模型对象的细节我们会在下个章节来说,这里我们继续来看调用链
AbstractConfig的构造器初始化一共有两个,第一个步骤就是创建一个应用程序模型对象ApplicationModel,刚刚我们在AbstractMethodConfig的构造器中了解到使用这个代码ApplicationModel.defaultModel().getDefaultModule()创建了个模块模型对象ModuleModel,具体他们细节我们下一章细说,了解了子类型AbstractMethodConfig的构造器是带参数的那我们就直接看第二个构造器
public AbstractConfig() {
this(ApplicationModel.defaultModel());
}
将会调用第二个构造器初始化域模型
public AbstractConfig(ScopeModel scopeModel) {
this.setScopeModel(scopeModel);
}
当前类型设置ScopeModel类型对象
public final void setScopeModel(ScopeModel scopeModel) {
//第一次初始化的当前成员变量是空的可以设置变量
if (this.scopeModel != scopeModel) {
//检查参数是否合法
checkScopeModel(scopeModel);
//初始化对象
this.scopeModel = scopeModel;
// reinitialize spi extension and change referenced config's scope model
//被子类重写的方法,根据多态会调用具体子类型的这个方法我们下面来看
//子类应该重写此方法以初始化其SPI扩展并更改引用的配置的范围模型。
this.postProcessAfterScopeModelChanged(oldScopeModel, this.scopeModel);
}
}
检查ScopeModel参数是否合法,合法的参数是不能为空并且必须是ApplicationModel类型或者子类型
2.3.2.1 重写的postProcessAfterScopeModelChanged调用逻辑
当ScopeModel模型对象发生了改变,上面调用了postProcessAfterScopeModelChanged方法来通知模型对象改变的时候要执行的操作,根据多态重写的逻辑我们从实现类的postProcessAfterScopeModelChanged来看,在下面的调用链路中部分父类型并未实现postProcessAfterScopeModelChanged方法我们就直接忽略了
@Override
protected void postProcessAfterScopeModelChanged(ScopeModel oldScopeModel, ScopeModel newScopeModel) {
super.postProcessAfterScopeModelChanged(oldScopeModel, newScopeModel);
//初始化当前协议对象,通过扩展机制获取协议Protocol类型的对象
//初始化当前代理工厂对象,通过扩展机制获取ProxyFactory类型的对象
proxyFactory = this.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
}
第二个被调用到的方法为ServiceConfigBase的postProcessAfterScopeModelChanged方法
@Override
protected void postProcessAfterScopeModelChanged(ScopeModel oldScopeModel, ScopeModel newScopeModel) {
super.postProcessAfterScopeModelChanged(oldScopeModel, newScopeModel);
//当服务提供者配置对象不为空时候为服务提供者对象设置域模型,这里服务提供者对象仍旧为空,这个一般用在兼容Dubbo低版本
if (this.provider != null && this.provider.getScopeModel() != scopeModel) {
this.provider.setScopeModel(scopeModel);
}
}
第三个被调用到的是AbstractInterfaceConfig类型的postProcessAfterScopeModelChanged方法
@Override
protected void postProcessAfterScopeModelChanged(ScopeModel oldScopeModel, ScopeModel newScopeModel) {
super.postProcessAfterScopeModelChanged(oldScopeModel, newScopeModel);
// remove this config from old ConfigManager
// if (oldScopeModel != null && oldScopeModel instanceof ModuleModel) {
// ((ModuleModel)oldScopeModel).getConfigManager().removeConfig(this);
// }
// change referenced config's scope model
ApplicationModel applicationModel = ScopeModelUtil.getApplicationModel(scopeModel);
//为配置中心对象设置ApplicationModel类型对象(当前阶段配置中心配置对象为空)
if (this.configCenter != null && this.configCenter.getScopeModel() != applicationModel) {
this.configCenter.setScopeModel(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);
}
//这哥if判断和上面的上面是重复的估计是写代码人加班加的太久了,没注意看
if (this.metadataReportConfig != null && this.metadataReportConfig.getScopeModel() != applicationModel) {
this.metadataReportConfig.setScopeModel(applicationModel);
}
//如果注册中心配置列表不为空则为每个注册中心配置设置一个ApplicationModel类型对象(当前注册中心对象都为空)
if (CollectionUtils.isNotEmpty(this.registries)) {
this.registries.forEach(registryConfig -> {
if (registryConfig.getScopeModel() != applicationModel) {
registryConfig.setScopeModel(applicationModel);
}
});
}
}
最后被调用到的是最顶层父类型AbstractConfig的postProcessAfterScopeModelChanged方法
这个方法什么也没干只是在父类型创建的模版方法让子类型来重写用的
public ServiceConfigBase() {
//服务元数据对象创建
serviceMetadata = new ServiceMetadata();
//为服务元数据对象
serviceMetadata.addAttribute("ORIGIN_CONFIG", this);
}
注意, ServiceMetadata这个类目前在Dubbo中没有用法。与服务级别相关的数据,例如名称、版本、业务服务的类加载器、安全信息等,还带有用于扩展的AttributeMap。
服务配置对象的创建过程就这样结束了,当然有一些细节会放到后面来写
上面主要顺序是按照代码执行的顺序来写的部分地方可能稍微做了调整,如果有条件的同学一定要自己进行DEBUG了解下细节.
关于服务配置官网提供了xml的配置信息这里我拷贝过来,可以做为参考:
当然这个配置不是最新的比如服务配置的标签配置tag,
warmup 预热时间单位毫秒,暂时还没有说明
技术咨询与支持,可以扫描微信公众号进行回复咨询