一,dubbo的分层架构
因为是第一篇,这些基础的东西需要先了解,对后面阅读源码也有好处,只做简单介绍,详细的可以看dubbo的官方手册。
1,Service层:该层与实际的业务内容相关,根据服务提供方和消费方提供对应的接口和实现
2,Config层:负责解析spring的配置文件,主要涉及ServiceConfig和ReferenceConfig
3,Proxy层:服务接口透明代理,生成服务的客户端Stub和服务端Skeleton,已ServiceProxy为中心,扩展接口为ProxyFactory
4,Registry层:封装服务地址的注册和发现,以服务URL为中心,扩展为RegistryFactory,Registry和RegistryService,可能没有服务注册中心,此时服务提供方直接暴露服务。
5,Cluster层:封装多个提供者的路由及负载均衡,并桥接注册中心,以Invoker为中心,扩展接口为Cluster,Directory,Router和LoadBalance,将多个服务提供方组合为一个服务提供方,实现对服务消费方来透明,只需要与一个服务提供方进行交互。
6,Monitor层:RPC调用次数和调用时间监控,以Statistics为中心,扩展接口为MonitorFactory,Monitor和MonitorService
7,Protocol层:封装RPC调用,以Invocation和Result为中心,扩展接口为Protocol,Invoker和Exporter。Protocol是服务域,是Invoker暴露和引用的主功能入口,负责Invoker的生命周期管理。Invoker是实体域,是Dubbo的核心模型,其他模型都向他靠拢或者转换为它,它代表一个可执行体,可以向它发起Invoke调用,它有可能是一个本地实现或者一个远程的实现或者一个集群的实现
8,Exchange层:封装请求响应模型,同步转异步,以Request和Response为中心,扩展接口为Exchanger,ExchangeChannel,ExchangeClient和ExchangeServer。
9,Transport层:抽象mina和netty为统一接口,以Message为中心,扩展接口为Channel,Transport,Client,Server和Codec。
10,Serialize层:可复用的一些工具,扩展接口为Serialization,ObjectInput,ObjectOutput和ThreadPool。
二,代码模块划分
1,dubbo-common 公共逻辑模块,包括Util类和通用模型。
2,dubbo-remoting 远程通讯模块,相当于Dubbo协议的实现,如果RPC用RMI协议则不需要使用此包。
3,dubbo-rpc 远程调用模块,抽象各种协议,以及动态代理,只包含一对一的调用,不关心集群的管理。
4,dubbo-cluster 集群模块,将多个服务提供方伪装为一个提供方,包括:负载均衡, 容错,路由等,集群的地址列表可以是静态配置的,也可以是由注册中心下发。
5,dubbo-registry 注册中心模块,基于注册中心下发地址的集群方式,以及对各种注册中心的抽象。
dubbo-monitor 监控模块,统计服务调用次数,调用时间的,调用链跟踪的服务。
6,dubbo-config 配置模块,是Dubbo对外的API,用户通过Config使用Dubbo,隐藏Dubbo所有细节。
7,dubbo-container 容器模块,是一个Standlone的容器,以简单的Main加载Spring启动,因为服务通常不需要Tomcat/JBoss等Web容器的特性,没必要用Web容器去加载服务
三,dubbo-config模块的代码阅读
1,beanutil包(主要是对class的一些定义和对反射的封装)
1.1 JavaBeanAccessor
(这个类相对容易理解,看定义和方法就可以了)
public enum JavaBeanAccessor {/** Field accessor. */FIELD,/** Method accessor.*/METHOD,/** Method prefer to field. */ALL;public static boolean isAccessByMethod(JavaBeanAccessor accessor) {return METHOD.equals(accessor) || ALL.equals(accessor);}public static boolean isAccessByField(JavaBeanAccessor accessor) {return FIELD.equals(accessor) || ALL.equals(accessor);}}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
1.2,JavaBeanDescriptor类。
该类主要定义了表示不同类型的常量
public final class JavaBeanDescriptor implements Serializable, Iterable<Map.Entry<Object, Object>> {private static final long serialVersionUID = -8505586483570518029L;public static final int TYPE_CLASS = 1;public static final int TYPE_ENUM = 2;public static final int TYPE_COLLECTION = 3;public static final int TYPE_MAP = 4;public static final int TYPE_ARRAY = 5;public static final int TYPE_PRIMITIVE = 6;public static final int TYPE_BEAN = 7;private static final String ENUM_PROPERTY_NAME = "name";private static final String CLASS_PROPERTY_NAME = "name";private static final String PRIMITIVE_PROPERTY_VALUE = "value";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
1.3,JavaBeanSerializeUtil
该类对对象进行序列化成JavaBeanDescriptor。以及可以将JavaBeanDescriptor反序列化为对象。注意里面使用的cache类型为IdentityHashMap。
2,bytecode包
2.1 Proxy类
生成代理对象的工具类,主要是基于javassist的实现
public abstract class Proxy
{private static final AtomicLong PROXY_CLASS_COUNTER = new AtomicLong(0);private static final String PACKAGE_NAME = Proxy.class.getPackage().getName();public static final InvocationHandler RETURN_NULL_INVOKER = new InvocationHandler(){public Object invoke(Object proxy, Method method, Object[] args){ return null; }};public static final InvocationHandler THROW_UNSUPPORTED_INVOKER = new InvocationHandler(){public Object invoke(Object proxy, Method method, Object[] args){ throw new UnsupportedOperationException("Method [" + ReflectUtils.getName(method) + "] unimplemented."); }};private static final Map<ClassLoader, Map<String, Object>> ProxyCacheMap = new WeakHashMap<ClassLoader, Map<String, Object>>();private static final Object PendingGenerationMarker = new Object();/*** Get proxy.* * @param ics interface class array.* @return Proxy instance.*/public static Proxy getProxy(Class<?>... ics){return getProxy(ClassHelper.getCallerClassLoader(Proxy.class), ics);}/*** Get proxy.* @param cl class loader.* @param ics interface class array.* * @return Proxy instance.*/public static Proxy getProxy(ClassLoader cl, Class<?>... ics){if( ics.length > 65535 )throw new IllegalArgumentException("interface limit exceeded");StringBuilder sb = new StringBuilder();for(int i=0;i<ics.length;i++){String itf = ics[i].getName();if( !ics[i].isInterface() )throw new RuntimeException(itf + " is not a interface.");Class<?> tmp = null;try{tmp = Class.forName(itf, false, cl);}catch(ClassNotFoundException e){}if( tmp != ics[i] )throw new IllegalArgumentException(ics[i] + " is not visible from class loader");sb.append(itf).append(';');}String key = sb.toString();Map<String, Object> cache;synchronized( ProxyCacheMap ){cache = ProxyCacheMap.get(cl);if( cache == null ){cache = new HashMap<String, Object>();ProxyCacheMap.put(cl, cache);}}Proxy proxy = null;synchronized( cache ){do{Object value = cache.get(key);if( value instanceof Reference<?> ){proxy = (Proxy)((Reference<?>)value).get();if( proxy != null )return proxy;}if( value == PendingGenerationMarker ){try{ cache.wait(); }catch(InterruptedException e){}}else{cache.put(key, PendingGenerationMarker);break;}}while( true );}long id = PROXY_CLASS_COUNTER.getAndIncrement();String pkg = null;ClassGenerator ccp = null, ccm = null;try{ccp = ClassGenerator.newInstance(cl);Set<String> worked = new HashSet<String>();List<Method> methods = new ArrayList<Method>();for(int i=0;i<ics.length;i++){if( !Modifier.isPublic(ics[i].getModifiers()) ){String npkg = ics[i].getPackage().getName();if( pkg == null ){pkg = npkg;}else{if( !pkg.equals(npkg) )throw new IllegalArgumentException("non-public interfaces from different packages");}}ccp.addInterface(ics[i]);for( Method method : ics[i].getMethods() ){String desc = ReflectUtils.getDesc(method);if( worked.contains(desc) )continue;worked.add(desc);int ix = methods.size();Class<?> rt = method.getReturnType();Class<?>[] pts = method.getParameterTypes();StringBuilder code = new StringBuilder("Object[] args = new Object[").append(pts.length).append("];");for(int j=0;j<pts.length;j++)code.append(" args[").append(j).append("] = ($w)$").append(j+1).append(";");code.append(" Object ret = handler.invoke(this, methods[" + ix + "], args);");if( !Void.TYPE.equals(rt) )code.append(" return ").append(asArgument(rt, "ret")).append(";");methods.add(method);ccp.addMethod(method.getName(), method.getModifiers(), rt, pts, method.getExceptionTypes(), code.toString());}}if( pkg == null )pkg = PACKAGE_NAME;/*** 创建代理实例对象ProxyInstance* 类名为 pkg + “.poxy”+id = 包名 + “.poxy” +自增数值* 添加静态字段Method[] methods;* 添加实例对象InvokerInvocationHandler hanler* 添加构造器参数是InvokerInvocationHandler* 添加无参构造器* 利用工具类ClassGenerator生成对应的字节码**/String pcn = pkg + ".proxy" + id;ccp.setClassName(pcn);ccp.addField("public static java.lang.reflect.Method[] methods;");ccp.addField("private " + InvocationHandler.class.getName() + " handler;");ccp.addConstructor(Modifier.PUBLIC, new Class<?>[]{ InvocationHandler.class }, new Class<?>[0], "handler=$1;");ccp.addDefaultConstructor();Class<?> clazz = ccp.toClass();clazz.getField("methods").set(null, methods.toArray(new Method[0]));/*** 创建代理对象,它的newInstance(handler)方法用来创建基于我们接口的代理* 代理对象名Proxy + id,继承于Proxy, 所以要实现newInstance方法* 添加默认构造器* 实现方法newInstance代码, new pcn(hadler) 这里pcn就是前面生成的代理对象类名* 利用工具类ClassGenerator生成字节码并实例化对象返回**/String fcn = Proxy.class.getName() + id;ccm = ClassGenerator.newInstance(cl);ccm.setClassName(fcn);ccm.addDefaultConstructor();ccm.setSuperClass(Proxy.class);ccm.addMethod("public Object newInstance(" + InvocationHandler.class.getName() + " h){ return new " + pcn + "($1); }");Class<?> pc = ccm.toClass();proxy = (Proxy)pc.newInstance();}catch(RuntimeException e){throw e;}catch(Exception e){throw new RuntimeException(e.getMessage(), e);}finally{if( ccp != null )ccp.release();if( ccm != null )ccm.release();synchronized( cache ){if( proxy == null )cache.remove(key);elsecache.put(key, new WeakReference<Proxy>(proxy));cache.notifyAll();}}return proxy;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
2.2 Wrapper类
是生成“运行时class代码”的工具类,
主要的方法有
1,makeWrapper类,生成一个继承于Wrapper的类
2,
public static Wrapper getWrapper(Class<?> c){while( ClassGenerator.isDynamicClass(c) ) c = c.getSuperclass();if( c == Object.class )return OBJECT_WRAPPER;Wrapper ret = WRAPPER_MAP.get(c);if( ret == null ) {ret = makeWrapper(c);WRAPPER_MAP.put(c,ret);}return ret;
}
3,extension包
这是一个动态扩展包,dubbo包含了@SPI @Adaptive注解。dubbo如何利用配置和注解来做动态扩展呢?
3.1 ExtensionFactory类
根据class返回一个instance
@SPI
public interface ExtensionFactory {/*** Get extension.* * @param type object type.* @param name object name.* @return object instance.*/<T> T getExtension(Class<T> type, String name);}
接下来查看它的三个实现类
3.1.1 SpringExtensionFactory类
从ApplicationContext 获取这个bean
3.1.2 AdaptiveExtensionFactory类
@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {private final List<ExtensionFactory> factories;public AdaptiveExtensionFactory() {ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();for (String name : loader.getSupportedExtensions()) { list.add(loader.getExtension(name));}factories = Collections.unmodifiableList(list);}public <T> T getExtension(Class<T> type, String name) {for (ExtensionFactory factory : factories) {T extension = factory.getExtension(type, name);if (extension != null) {return extension;}}return null;}}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
相当于一个代理入口,他会遍历当前系统中所有的ExtensionFactory实现来获取指定的扩展实现,获取到扩展实现或遍历完所有的ExtensionFactory实现。这里调用了ExtensionLoader的getSupportedExtensions方法来获取ExtensionFactory的所有实现,又回到了ExtensionLoader类。
3.1.3 SpiExtensionFactory类
用ExtensionLoader来动态扩展,获取instance
3.2 ExtensionLoader类(重点,将详细解读)
每一个ExtensionLoader实例仅负责加载特定SPI扩展的实现,因此想要获取某个扩展的实现,首先要获取到该扩展对应的ExtensionLoader实例,下面我们就来看一下获取ExtensionLoader实例的工厂方法getExtensionLoade
@SuppressWarnings("unchecked")public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {if (type == null)throw new IllegalArgumentException("Extension type == null");if(!type.isInterface()) {throw new IllegalArgumentException("Extension type(" + type + ") is not interface!");}if(!withExtensionAnnotation(type)) {throw new IllegalArgumentException("Extension type(" + type + ") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!");}ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);if (loader == null) {EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);}return loader;}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
接下来查看私有构造函数
private ExtensionLoader(Class<?> type) {this.type = type;objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
}
从这个方法可以看到,我们调用getAdaptiveExtension来获取一个自适应的实现,接下来看看它的实现
public T getAdaptiveExtension() {Object instance = cachedAdaptiveInstance.get(); if (instance == null) {if(createAdaptiveInstanceError == null) {synchronized (cachedAdaptiveInstance) {instance = cachedAdaptiveInstance.get();if (instance == null) {try {instance = createAdaptiveExtension(); cachedAdaptiveInstance.set(instance);} catch (Throwable t) {createAdaptiveInstanceError = t;throw new IllegalStateException("fail to create adaptive instance: " + t.toString(), t);}}}}else {throw new IllegalStateException("fail to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError);}}return (T) instance;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
首先检查缓存的adaptiveInstance是否存在,如果存在则直接使用,否则的话调用createAdaptiveExtension方法来创建新的adaptiveInstance并且缓存起来。也就是说对于某个扩展点,每次调用ExtensionLoader.getAdaptiveExtension获取到的都是同一个实例。
private Class<?> getAdaptiveExtensionClass() {getExtensionClasses(); if (cachedAdaptiveClass != null) {return cachedAdaptiveClass;}return cachedAdaptiveClass = createAdaptiveExtensionClass();
}private Map<String, Class<?>> getExtensionClasses() {Map<String, Class<?>> classes = cachedClasses.get(); if (classes == null) {synchronized (cachedClasses) {classes = cachedClasses.get();if (classes == null) {classes = loadExtensionClasses(); cachedClasses.set(classes);}}}return classes;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
在getExtensionClasses方法中,首先检查缓存的cachedClasses,如果没有再调用loadExtensionClasses方法来加载,加载完成之后就会进行缓存。也就是说对于每个扩展点,其实现的加载只会执行一次。我们看下loadExtensionClasses方法:
private Map<String, Class<?>> loadExtensionClasses() {final SPI defaultAnnotation = type.getAnnotation(SPI.class);if(defaultAnnotation != null) {String value = defaultAnnotation.value(); if(value != null && (value = value.trim()).length() > 0) {String[] names = NAME_SEPARATOR.split(value);if(names.length > 1) { throw new IllegalStateException("more than 1 default extension name on extension " + type.getName()+ ": " + Arrays.toString(names));}if(names.length == 1) cachedDefaultName = names[0];}}Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY);loadFile(extensionClasses, DUBBO_DIRECTORY);loadFile(extensionClasses, SERVICES_DIRECTORY);return extensionClasses;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
从代码里面可以看到,在loadExtensionClasses中首先会检测扩展点在@SPI注解中配置的默认扩展实现的名称,并将其赋值给cachedDefaultName属性进行缓存,后面想要获取该扩展点的默认实现名称就可以直接通过访问cachedDefaultName字段来完成,比如getDefaultExtensionName方法就是这么实现的。从这里的代码中又可以看到,具体的扩展实现类型,是通过调用loadFile方法来加载,分别从一下三个地方加载:
META-INF/dubbo/internal/
META-INF/dubbo/
META-INF/services/
创建自适应扩展点实现类型和实例化就已经完成了,下面就来看下扩展点自动注入的实现injectExtension:
private T injectExtension(T instance) {try {if (objectFactory != null) {for (Method method : instance.getClass().getMethods()) {if (method.getName().startsWith("set")&& method.getParameterTypes().length == 1&& Modifier.isPublic(method.getModifiers())) {// 处理所有set方法Class<?> pt = method.getParameterTypes()[0]try {// 获取setter对应的property名称String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : ""Object object = objectFactory.getExtension(pt, property)if (object != null) { // 如果不为空,说set方法的参数是扩展点类型,那么进行注入method.invoke(instance, object)}} catch (Exception e) {logger.error("fail to inject via method " + method.getName()+ " of interface " + type.getName() + ": " + e.getMessage(), e)}}}}} catch (Exception e) {logger.error(e.getMessage(), e)}return instance
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
这里可以看到,扩展点自动注入的一句就是根据setter方法对应的参数类型和property名称从ExtensionFactory中查询,如果有返回扩展点实例,那么就进行注入操作。到这里getAdaptiveExtension方法就分析完毕了。
接下来看看getExtension
public T getExtension(String name) {if (name == null || name.length() == 0)throw new IllegalArgumentException("Extension name == null");if ("true".equals(name)) { return getDefaultExtension();}Holder<Object> holder = cachedInstances.get(name);if (holder == null) {cachedInstances.putIfAbsent(name, new Holder<Object>());holder = cachedInstances.get(name);}Object instance = holder.get();if (instance == null) {synchronized (holder) {instance = holder.get();if (instance == null) {instance = createExtension(name);holder.set(instance);}}}return (T) instance;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
private T createExtension(String name) {Class<?> clazz = getExtensionClasses().get(name); if (clazz == null) {throw findException(name);}try {T instance = (T) EXTENSION_INSTANCES.get(clazz); if (instance == null) {EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());instance = (T) EXTENSION_INSTANCES.get(clazz);}injectExtension(instance); Set<Class<?>> wrapperClasses = cachedWrapperClasses;if (wrapperClasses != null && wrapperClasses.size() > 0) {for (Class<?> wrapperClass : wrapperClasses) {instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));}}return instance;} catch (Throwable t) {throw new IllegalStateException("Extension instance(name: " + name + ", class: " +type + ") could not be instantiated: " + t.getMessage(), t);}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
从代码中可以看到,内部调用了getExtensionClasses方法来获取当前扩展的所有实现,而getExtensionClassse方法会在第一次被调用的时候将结果缓存到cachedClasses变量中,后面的调用就直接从缓存变量中获取了。这里还可以看到一个缓存EXTENSION_INSTANCES,这个缓存是ExtensionLoader的静态成员,也就是全局缓存,存放着所有的扩展点实现类型与其对应的已经实例化的实例对象(是所有扩展点,不是某一个扩展点),也就是说所有的扩展点实现在dubbo中最多都只会有一个实例
接下来看看getActivateExtension
方法主要获取当前扩展的所有可自动激活的实现。可根据入参(values)调整指定实现的顺序,在这个方法里面也使用到getExtensionClasses方法中收集的缓存数据
public List<T> getActivateExtension(URL url, String[] values, String group) {List<T> exts = new ArrayList<T>();List<String> names = values == null ? new ArrayList<String>(0) : Arrays.asList(values); if (! names.contains(Constants.REMOVE_VALUE_PREFIX + Constants.DEFAULT_KEY)) {getExtensionClasses(); for (Map.Entry<String, Activate> entry : cachedActivates.entrySet()) { String name = entry.getKey();Activate activate = entry.getValue();if (isMatchGroup(group, activate.group())) { T ext = getExtension(name); if (! names.contains(name)&& ! names.contains(Constants.REMOVE_VALUE_PREFIX + name) && isActive(activate, url)) {exts.add(ext);}}}Collections.sort(exts, ActivateComparator.COMPARATOR); }List<T> usrs = new ArrayList<T>();for (int i = 0; i < names.size(); i ++) { String name = names.get(i);if (! name.startsWith(Constants.REMOVE_VALUE_PREFIX)&& ! names.contains(Constants.REMOVE_VALUE_PREFIX + name)) { if (Constants.DEFAULT_KEY.equals(name)) { if (usrs.size() > 0) { exts.addAll(0, usrs); usrs.clear(); }} else {T ext = getExtension(name);usrs.add(ext);}}}if (usrs.size() > 0) { exts.addAll(usrs); }return exts;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
四,URL
URL 本来是用来远程寻址的,dubbo 用它来暴露服务
所有扩展点参数都包含URL参数,URL作为上下文信息贯穿整个扩展点设计体系。
URL采用标准格式:protocol://username:password@host:port/path?key=value&key=value
例如:injvm://127.0.0.1/com.alibaba.dubbo.demo.DemoService?anyhost=true&application=demo-provider&dubbo=2.0.0&generic=false&interface=com.alibaba.dubbo.demo.DemoService&loadbalance=roundrobin&methods=sayHello