dubbo提供了四种配置方式:
1. api配置
2. 属性配置
3. xml配置
4. 注解配置
配置一览:
配置之间的关系如下所示:
分为四个部分:
1. application-shared
2. provider-side
3. consumer-side
4. sub-config
先来看一段官方给的消费者的初始化代码:
//当前应用配置 ApplicationConfig application = new ApplicationConfig(); application.setName("yyy"); //注册中心配置 RegistryConfig registry = new RegistryConfig(); registry.setAddress("10.20.130.230:9090"); registry.setUsername("aaa"); registry.setPassword("bbb"); //链接远程服务,内部封装了和注册中心以及远程服务的链接 ReferenceConfig<XxxService> reference = new ReferenceConfig<XxxService>(); reference.setApplication(application); reference.setRegistry(registry); //多个注册中心可以用setRegisters() reference.setInterface(XxxService.class); reference.setVersion("1.0.0"); XxxService xxxService = reference.get(); //封装了RPC的细节调用远程服务
- 可以看到创建了ApplicationConfig和RegistryConfig然后设置给ReferenceConfig
除了ArgumentConfig,都继承自com.alibaba.dubbo.config.AbstractConfig,主要提供了解析和校验相关的公共方法:
protected String id;id属性主要用于除api配置其余三种的对象之间的引用,比如:<dubbo:service provider="${PROVIDER_ID}">其中的PROVIDER_ID即为<dubbo:provider>的id属性
@SuppressWarnings("unchecked") protected static void appendParameters(Map<String, String> parameters, Object config, String prefix) { 用于将配置对象的属性添加到集合代码如下
@SuppressWarnings("unchecked") protected static void appendParameters(Map<String, String> parameters, Object config, String prefix) { if (config == null) { return; } Method[] methods = config.getClass().getMethods(); for (Method method : methods) { try { String name = method.getName(); if ((name.startsWith("get") || name.startsWith("is")) && !"getClass".equals(name) && Modifier.isPublic(method.getModifiers()) && method.getParameterTypes().length == 0 && isPrimitive(method.getReturnType())) {//返回值为基本的数据类型 Parameter parameter = method.getAnnotation(Parameter.class);//获取方法上面的@Parameter 注解 if (method.getReturnType() == Object.class || parameter != null && parameter.excluded()) {//注解值是否配置了可以忽略,excluded continue; } int i = name.startsWith("get") ? 3 : 2; String prop = StringUtils.camelToSplitName(name.substring(i, i + 1).toLowerCase() + name.substring(i + 1), ".");//截取方法的属性名 String key; if (parameter != null && parameter.key() != null && parameter.key().length() > 0) {//parameter注解设置了key值 key = parameter.key(); } else { key = prop;//否则key就取方法的属性值 } Object value = method.invoke(config, new Object[0]);//反射调用get方法获取对应的value String str = String.valueOf(value).trim(); if (value != null && str.length() > 0) { if (parameter != null && parameter.escaped()) {//parameter 是否配置了转义 str = URL.encode(str); } if (parameter != null && parameter.append()) {//是否拼接默认属性,详情见下方 String pre = (String) parameters.get(Constants.DEFAULT_KEY + "." + key); if (pre != null && pre.length() > 0) { str = pre + "," + str; } //开始拼接 pre = (String) parameters.get(key); if (pre != null && pre.length() > 0) { str = pre + "," + str; } } if (prefix != null && prefix.length() > 0) { key = prefix + "." + key; } parameters.put(key, str); } else if (parameter != null && parameter.required()) {//是否必填 throw new IllegalStateException(config.getClass().getSimpleName() + "." + key + " == null"); } } else if ("getParameters".equals(name)//返回值是map类型的话.需要遍历map逐个添加到parameters中去 && Modifier.isPublic(method.getModifiers()) && method.getParameterTypes().length == 0 && method.getReturnType() == Map.class) { Map<String, String> map = (Map<String, String>) method.invoke(config, new Object[0]); if (map != null && map.size() > 0) { String pre = (prefix != null && prefix.length() > 0 ? prefix + "." : ""); for (Map.Entry<String, String> entry : map.entrySet()) { parameters.put(pre + entry.getKey().replace('-', '.'), entry.getValue()); } } } } catch (Exception e) { throw new IllegalStateException(e.getMessage(), e); } } }
关于@Paramter注解中的append属性理解
此处的getFilter()和getListener()方法配置的append=true
protected static void appendAttributes(Map<Object, Object> parameters, Object config, String prefix) {
将@Parameter(attribute = true)配置的对象属性添加到参数集合,代码:
protected static void appendAttributes(Map<Object, Object> parameters, Object config, String prefix) { if (config == null) { return; } Method[] methods = config.getClass().getMethods(); for (Method method : methods) { try { String name = method.getName(); if ((name.startsWith("get") || name.startsWith("is")) && !"getClass".equals(name) && Modifier.isPublic(method.getModifiers()) && method.getParameterTypes().length == 0 && isPrimitive(method.getReturnType())) { Parameter parameter = method.getAnnotation(Parameter.class); if (parameter == null || !parameter.attribute()) continue; String key; if (parameter.key() != null && parameter.key().length() > 0) { key = parameter.key(); } else { int i = name.startsWith("get") ? 3 : 2; key = name.substring(i, i + 1).toLowerCase() + name.substring(i + 1); } Object value = method.invoke(config, new Object[0]); if (value != null) { if (prefix != null && prefix.length() > 0) { key = prefix + "." + key; } parameters.put(key, value); } } } catch (Exception e) { throw new IllegalStateException(e.getMessage(), e); } } }
代码和appendParameter基本一样,appendProperties和属性配置相关的,appendAnnotation和注解配置相关的,都暂且先不分析
文章来源: dubbo源码分析--api配置(一)