dubbo源码深度解读一之common模块
来源:互联网 发布:windows10装mac系统 编辑:程序博客网 时间:2024/06/07 20:18
前言:或许很多人会使用dubbo,但是阅读源码将使我们更加了解它,以及在未来对它进行改进优化。我就先把flag立在这里了,接下来这阵子将会深入源码进行学习和优化。做为一个要使用dubbo的程序员,必须需要深入理解它,因为dubbo已经停止了维护。
一,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,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; /** @see com.alibaba.dubbo.common.utils.ReflectUtils#isPrimitive(Class) */ 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.3,JavaBeanSerializeUtil
该类对对象进行序列化成JavaBeanDescriptor。以及可以将JavaBeanDescriptor反序列化为对象。注意里面使用的cache类型为IdentityHashMap。
2,bytecode包
2.1 Proxy类
生成代理对象的工具类,主要是基于javassist的实现
public abstract class Proxy{ //利用AtomicLong自增获取一个long数组做为生存类的后缀,防止冲突 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."); } }; //缓存的map对象 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(';'); } // use interface class name list as key. String key = sb.toString(); //通过classloader去缓存map中拿出对应的map。 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; //如果查询获得对象,则返回,否则把key和PendingGenerationMarker插入 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; // create ProxyInstance class. /** * 创建代理实例对象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])); // create Proxy class. /** * 创建代理对象,它的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 { // release ClassGenerator if( ccp != null ) ccp.release(); if( ccm != null ) ccm.release(); synchronized( cache ) { if( proxy == null ) cache.remove(key); else cache.put(key, new WeakReference<Proxy>(proxy)); cache.notifyAll(); } } return proxy; }
2.2 Wrapper类
是生成“运行时class代码”的工具类,
主要的方法有
1,makeWrapper类,生成一个继承于Wrapper的类
2,
public static Wrapper getWrapper(Class<?> c){ while( ClassGenerator.isDynamicClass(c) ) // can not wrapper on dynamic class. c = c.getSuperclass(); //Object类型的 if( c == Object.class ) return OBJECT_WRAPPER; //先去Wrapper缓存中查找 Wrapper ret = WRAPPER_MAP.get(c); if( ret == null ) { //缓存中不存在,生成Wrapper类,放到缓存 ret = makeWrapper(c); WRAPPER_MAP.put(c,ret); } return ret;}
3,extension包
这是一个动态扩展包,dubbo包含了@SPI @Adaptive注解。dubbo如何利用配置和注解来做动态扩展呢?
3.1 ExtensionFactory类
根据class返回一个instance
@SPIpublic 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类
@Adaptivepublic 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()) { // 将所有ExtensionFactory实现保存起来 list.add(loader.getExtension(name)); } factories = Collections.unmodifiableList(list); } public <T> T getExtension(Class<T> type, String name) { // 依次遍历各个ExtensionFactory实现的getExtension方法,一旦获取到Extension即返回 // 如果遍历完所有的ExtensionFactory实现均无法找到Extension,则返回null for (ExtensionFactory factory : factories) { T extension = factory.getExtension(type, name); if (extension != null) { return extension; } } return null; }}
相当于一个代理入口,他会遍历当前系统中所有的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!"); } //只接受@SPI注解注释的接口类型 if(!withExtensionAnnotation(type)) { throw new IllegalArgumentException("Extension type(" + type + ") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!"); } //从缓存中获取对应的ExtensionLoader实例 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; }
接下来查看私有构造函数
private ExtensionLoader(Class<?> type) { this.type = type; // 如果扩展类型是ExtensionFactory,那么则设置为null // 这里通过getAdaptiveExtension方法获取一个运行时自适应的扩展类型(每个Extension只能有一个@Adaptive类型的实现,如果没有dubbo会动态生成一个类) 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(); // 没有缓存的实例,创建新的AdaptiveExtension实例 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;}
首先检查缓存的adaptiveInstance是否存在,如果存在则直接使用,否则的话调用createAdaptiveExtension方法来创建新的adaptiveInstance并且缓存起来。也就是说对于某个扩展点,每次调用ExtensionLoader.getAdaptiveExtension获取到的都是同一个实例。
private Class<?> getAdaptiveExtensionClass() { getExtensionClasses(); // 加载当前Extension的所有实现,如果有@Adaptive类型,则会赋值为cachedAdaptiveClass属性缓存起来 if (cachedAdaptiveClass != null) { return cachedAdaptiveClass; } return cachedAdaptiveClass = createAdaptiveExtensionClass(); // 没有找到@Adaptive类型实现,则动态创建一个AdaptiveExtensionClass}private Map<String, Class<?>> getExtensionClasses() { Map<String, Class<?>> classes = cachedClasses.get(); // 判断是否已经加载了当前Extension的所有实现类 if (classes == null) { synchronized (cachedClasses) { classes = cachedClasses.get(); if (classes == null) { classes = loadExtensionClasses(); // 如果还没有加载Extension的实现,则进行扫描加载,完成后赋值给cachedClasses变量 cachedClasses.set(classes); } } } return classes;}
在getExtensionClasses方法中,首先检查缓存的cachedClasses,如果没有再调用loadExtensionClasses方法来加载,加载完成之后就会进行缓存。也就是说对于每个扩展点,其实现的加载只会执行一次。我们看下loadExtensionClasses方法:
private Map<String, Class<?>> loadExtensionClasses() { final SPI defaultAnnotation = type.getAnnotation(SPI.class); if(defaultAnnotation != null) { String value = defaultAnnotation.value(); // 解析当前Extension配置的默认实现名,赋值给cachedDefaultName属性 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;}
从代码里面可以看到,在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];// 获取set方法参数类型 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); // 根据类型,名称信息从ExtensionFactory获取 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;}
这里可以看到,扩展点自动注入的一句就是根据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;}
private T createExtension(String name) { Class<?> clazz = getExtensionClasses().get(name); // getExtensionClass内部使用cachedClasses缓存 if (clazz == null) { throw findException(name); } try { T instance = (T) EXTENSION_INSTANCES.get(clazz); // 从已创建Extension实例缓存中获取 if (instance == null) { EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance()); instance = (T) EXTENSION_INSTANCES.get(clazz); } injectExtension(instance); // 属性注入 // Wrapper类型进行包装,层层包裹 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); }}
从代码中可以看到,内部调用了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); // 解析配置要使用的名称 // 如果未配置"-default",则加载所有Activates扩展(names指定的扩展) if (! names.contains(Constants.REMOVE_VALUE_PREFIX + Constants.DEFAULT_KEY)) { getExtensionClasses(); // 加载当前Extension所有实现,会获取到当前Extension中所有@Active实现,赋值给cachedActivates变量 for (Map.Entry<String, Activate> entry : cachedActivates.entrySet()) { // 遍历当前扩展所有的@Activate扩展 String name = entry.getKey(); Activate activate = entry.getValue(); if (isMatchGroup(group, activate.group())) { // 判断group是否满足,group为null则直接返回true T ext = getExtension(name); // 获取扩展示例 // 排除names指定的扩展;并且如果names中没有指定移除该扩展(-name),且当前url匹配结果显示可激活才进行使用 if (! names.contains(name) && ! names.contains(Constants.REMOVE_VALUE_PREFIX + name) && isActive(activate, url)) { exts.add(ext); } } } Collections.sort(exts, ActivateComparator.COMPARATOR); // 默认排序 } // 对names指定的扩展进行专门的处理 List<T> usrs = new ArrayList<T>(); for (int i = 0; i < names.size(); i ++) { // 遍历names指定的扩展名 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)) { // default表示上面已经加载并且排序的exts,将排在default之前的Activate扩展放置到default组之前,例如:ext1,default,ext2 if (usrs.size() > 0) { // 如果此时user不为空,则user中存放的是配置在default之前的Activate扩展 exts.addAll(0, usrs); // 注意index是0,放在default前面 usrs.clear(); // 放到default之前,然后清空 } } else { T ext = getExtension(name); usrs.add(ext); } } } if (usrs.size() > 0) { // 这里留下的都是配置在default之后的 exts.addAll(usrs); // 添加到default排序之后 } return exts;}
四,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
总结:
第一次看源码,还有很多不太理解的,但是随着越来越深入,会慢慢清晰,同时也借鉴了很多大牛的博客,如果有什么错误的地方,欢迎指出。
- dubbo源码深度解读一之common模块
- dubbo源码深度解读一之common模块
- dubbo源码深度解读二之config模块
- dubbo源码深度解读三之container模块
- dubbo源码深度解读四之remoting模块
- dubbo源码深度解读五之rpc模块
- dubbo源码深度解读六之cluster模块
- dubbo源码深度解读七之registery模块
- Dubbo ExtensionLoader源码解读
- dubbo源码解读
- Spark源码解读 deploy模块(一)
- 深度解剖dubbo源码
- 深度解剖dubbo源码
- 深度解剖dubbo源码
- AMPS:内存管理模块源码解读(一)
- Spring源码之SimpleAliasRegistry解读(一)
- 认识dubbo源码 一
- AFNetworking源码解读之AFSecurityPolicy模块中的Https验证
- 32.Android端向web端(服务器)提交数据(GET-POST-AsyncHttpClient)
- 【CJ Cup】分解
- python 项目结构
- 牛客网编程基础9-11
- 订单分库分表实践总结
- dubbo源码深度解读一之common模块
- 生产者和消费者
- 【HDU4405】Aeroplane chess
- Redis--(linux安装redis3.2.9--教程)
- Android开发之蓝牙(一)——基于SPP协议蓝牙模块通信
- php扩展研究之一(实现a+b)
- Android与web后台进行数据交互的三种方式
- 数据结构之顺序栈的一些基本操作
- 【转】数据库索引的实现原理