复杂系统中可能出现想给不同dubbo服务指定不同Protocol和Registry的需求,显式逐个指定一定有效。
但是,显式逐个指定的做法过于繁琐。如果利用默认机制,用较少显式配置就实现目标就再好不过了。
此外,举个失误案例,想当然认为,服务会使用被定义在同一个xml中的Protocol和Registry,但实际情况不是这样。
本文尝试从源码一级分析spring下dubbo启动时如何选择Protocol和Registry。
先给结论
会用整个spring上下文中的所有Protocol和Registry
不论是xml还是@Configuration,无论是否在一个中
如有特殊配置的话,可能会少用些
代码一级的解释
dubbo的xml配置下,<dubbo:>命名空间的元素方式会被DubboNamespaceHandler处理。
具体来说,<dubbo:service>和<dubbo:reference>会分别被上述Handler处理成ServiceBean和ReferenceBean并注册进上下文中。
在ServiceBean的public void afterPropertiesSet() throws Exception方法片段如下:
Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false);
if (registryConfigMap != null && registryConfigMap.size() > 0) {
List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>();
for (RegistryConfig config : registryConfigMap.values()) {
if (config.isDefault() == null || config.isDefault().booleanValue()) {
registryConfigs.add(config);
}
}
if (registryConfigs != null && !registryConfigs.isEmpty()) {
super.setRegistries(registryConfigs);
}
}
这段代码主要做的事如下
- 从
ApplicationContext中找出所有RegistryConfig类型的bean - 在这些bean中,找到未设置
default属性(为null)或default属性为true的,放入一个list中 - 若上述
list非null非空,则将其作为registries
至此可知选择Registry的两个标准
- 从
ApplicationContext中找出所有RegistryConfig - 未设置
default属性(为null)或default属性为true
在这段代码外,还有一个if判断,如下:
if ((getRegistries() == null || getRegistries().isEmpty())
&& (getProvider() == null || getProvider().getRegistries() == null || getProvider().getRegistries().isEmpty())
&& (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().isEmpty())) {
// 省略,前一段代码
}
这段判断的顺序主要为,依次判断ServiceBean自己,Provider,Application中是否没有registries配置
再回头看ServiceBean中整个afterPropertiesSet()方法
public void afterPropertiesSet() throws Exception {
// 略对Provider、Application和Module的配置
if ((getRegistries() == null || getRegistries().isEmpty())
&& (getProvider() == null || getProvider().getRegistries() == null || getProvider().getRegistries().isEmpty())
&& (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().isEmpty())) {
Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false);
if (registryConfigMap != null && registryConfigMap.size() > 0) {
List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>();
for (RegistryConfig config : registryConfigMap.values()) {
if (config.isDefault() == null || config.isDefault().booleanValue()) {
registryConfigs.add(config);
}
}
if (registryConfigs != null && !registryConfigs.isEmpty()) {
super.setRegistries(registryConfigs);
}
}
}
// 略对Monitor的配置
if ((getProtocols() == null || getProtocols().isEmpty())
&& (getProvider() == null || getProvider().getProtocols() == null || getProvider().getProtocols().isEmpty())) {
Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);
if (protocolConfigMap != null && protocolConfigMap.size() > 0) {
List<ProtocolConfig> protocolConfigs = new ArrayList<ProtocolConfig>();
for (ProtocolConfig config : protocolConfigMap.values()) {
if (config.isDefault() == null || config.isDefault().booleanValue()) {
protocolConfigs.add(config);
}
}
if (protocolConfigs != null && !protocolConfigs.isEmpty()) {
super.setProtocols(protocolConfigs);
}
}
}
// 略对Path的配置,export
}
其中可见,选择Registry和Protocol的逻辑大同小异