上一篇:dubbo3.0源码分析之ModuleDeployer各个组件进行初始化
前言
我们之前分析了ModuleDeployer如果对各个组件进行初始化,并且对老代码进行兼容的,我们再来看看dubbo是如何对服务实例进行刷新操作的
源码分析
refresh主要是把配置读取并设置到当前ServiceConfig的相关属性赋值到对应的配置上。通过之前的分析找到入口refresh方法;
AbstractConfig的refresh方法
public void refresh() {
/** 设置刷新标志位 */
refreshed.set(true);
try {
// check and init before do refresh
/** 预处理 */
preProcessRefresh();
Environment environment = getScopeModel().getModelEnvironment();
List<Map<String, String>> configurationMaps = environment.getConfigurationMaps();
// Search props starts with PREFIX in order
/** 获取搜索前缀,如:dubbo.service.org.apache.dubbo.demo.DemoService */
String preferredPrefix = null;
for (String prefix : getPrefixes()) {
if (ConfigurationUtils.hasSubProperties(configurationMaps, prefix)) {
preferredPrefix = prefix;
break;
}
}
if (preferredPrefix == null) {
preferredPrefix = getPrefixes().get(0);
}
// Extract sub props (which key was starts with preferredPrefix)
/** 组装接口配置信息成InmemoryConfiguration类 */
Collection<Map<String, String>> instanceConfigMaps = environment.getConfigurationMaps(this, preferredPrefix);
Map<String, String> subProperties = ConfigurationUtils.getSubProperties(instanceConfigMaps, preferredPrefix);
InmemoryConfiguration subPropsConfiguration = new InmemoryConfiguration(subProperties);
if (logger.isDebugEnabled()) {
String idOrName = "";
if (StringUtils.hasText(this.getId())) {
idOrName = "[id=" + this.getId() + "]";
} else {
String name = ReflectUtils.getProperty(this, "getName");
if (StringUtils.hasText(name)) {
idOrName = "[name=" + name + "]";
}
}
logger.debug("Refreshing " + this.getClass().getSimpleName() + idOrName +
" with prefix [" + preferredPrefix +
"], extracted props: " + subProperties);
}
assignProperties(this, environment, subProperties, subPropsConfiguration);
// process extra refresh of subclass, e.g. refresh method configs
/** 获取服务实例接口以及接口的方法及方法配置,刷新方法配置数据 */
processExtraRefresh(preferredPrefix, subPropsConfiguration);
} catch (Exception e) {
logger.error("Failed to override field value of config bean: " + this, e);
throw new IllegalStateException("Failed to override field value of config bean: " + this, e);
}
postProcessRefresh();
}
AbstractInterfaceConfig的processExtraRefresh方法
protected void processExtraRefresh(String preferredPrefix, InmemoryConfiguration subPropsConfiguration) {
if (StringUtils.hasText(interfaceName)) {
Class<?> interfaceClass;
try {
/** 通过反射获取接口名称对应的实现类 */
interfaceClass = ClassUtils.forName(interfaceName);
} catch (ClassNotFoundException e) {
// There may be no interface class when generic call
return;
}
if (!interfaceClass.isInterface()) {
throw new IllegalStateException(interfaceName+" is not an interface");
}
// Auto create MethodConfig/ArgumentConfig according to config props
/** 获取配置 */
Map<String, String> configProperties = subPropsConfiguration.getProperties();
Method[] methods;
try {
/** 后去接口实现类的所有方法 */
methods = interfaceClass.getMethods();
} catch (Throwable e) {
// NoClassDefFoundError may be thrown if interface class's dependency jar is missing
return;
}
for (Method method : methods) {
if (ConfigurationUtils.hasSubProperties(configProperties, method.getName())) {
/** 根据接口方法生成MethodConfig,一个MethodConfig可以理解为一个小接口 */
MethodConfig methodConfig = getMethodByName(method.getName());
// Add method config if not found
/** 如果为空则创建并调用addMethod方法添加至methods集合中 */
if (methodConfig == null) {
methodConfig = new MethodConfig();
methodConfig.setName(method.getName());
this.addMethod(methodConfig);
}
// Add argument config
// dubbo.service.{interfaceName}.{methodName}.{arg-index}.xxx=xxx
/** 获取方法的所有参数 */
java.lang.reflect.Parameter[] arguments = method.getParameters();
/** 根据接口方法的参数生成ArgumentConfig添加至MethodConfig中 */
for (int i = 0; i < arguments.length; i++) {
if (getArgumentByIndex(methodConfig, i) == null &&
hasArgumentConfigProps(configProperties, methodConfig.getName(), i)) {
ArgumentConfig argumentConfig = new ArgumentConfig();
argumentConfig.setIndex(i);
methodConfig.addArgument(argumentConfig);
}
}
}
}
// refresh MethodConfigs
/** 获取所有的MethodConfig并刷新其配置 */
List<MethodConfig> methodConfigs = this.getMethods();
if (methodConfigs != null && methodConfigs.size() > 0) {
// whether ignore invalid method config
Object ignoreInvalidMethodConfigVal = getEnvironment().getConfiguration()
.getProperty(ConfigKeys.DUBBO_CONFIG_IGNORE_INVALID_METHOD_CONFIG, "false");
boolean ignoreInvalidMethodConfig = Boolean.parseBoolean(ignoreInvalidMethodConfigVal.toString());
Class<?> finalInterfaceClass = interfaceClass;
List<MethodConfig> validMethodConfigs = methodConfigs.stream().filter(methodConfig -> {
methodConfig.setParentPrefix(preferredPrefix);
methodConfig.setScopeModel(getScopeModel());
methodConfig.refresh();
// verify method config
return verifyMethodConfig(methodConfig, finalInterfaceClass, ignoreInvalidMethodConfig);
}).collect(Collectors.toList());
this.setMethods(validMethodConfigs);
}
}
}