博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
2.2 dubbo-spi源码解析
阅读量:6438 次
发布时间:2019-06-23

本文共 24970 字,大约阅读时间需要 83 分钟。

1 package com.alibaba.dubbo.demo.test; 2  3 import com.alibaba.dubbo.common.extension.ExtensionLoader; 4 import com.alibaba.dubbo.rpc.Protocol; 5  6 public class TestExtension { 7     public static void main(String[] args) { 8         ExtensionLoader
loader = ExtensionLoader.getExtensionLoader(Protocol.class); 9 final Protocol dubboProtocol = loader.getExtension("dubbo");10 final Protocol adaptiveExtension = loader.getAdaptiveExtension();11 }12 }

讲解这三行代码的源码。

一  Protocol接口的定义

1 package com.alibaba.dubbo.rpc; 2  3 import com.alibaba.dubbo.common.URL; 4 import com.alibaba.dubbo.common.extension.Adaptive; 5 import com.alibaba.dubbo.common.extension.SPI; 6  7 /** 8  * Protocol. (API/SPI, Singleton, ThreadSafe) 9  */10 @SPI("dubbo")11 public interface Protocol {12 13     /**14      * 获取缺省端口,当用户没有配置端口时使用。15      *16      * @return 缺省端口17      */18     int getDefaultPort();19 20     /**21      * 暴露远程服务:
22 * 1. 协议在接收请求时,应记录请求来源方地址信息:RpcContext.getContext().setRemoteAddress();
23 * 2. export()必须是幂等的,也就是暴露同一个URL的Invoker两次,和暴露一次没有区别。
24 * 3. export()传入的Invoker由框架实现并传入,协议不需要关心。
25 *26 * @param
服务的类型27 * @param invoker 服务的执行体28 * @return exporter 暴露服务的引用,用于取消暴露29 * @throws RpcException 当暴露服务出错时抛出,比如端口已占用30 */31 @Adaptive32
Exporter
export(Invoker
invoker) throws RpcException;33 34 /**35 * 引用远程服务:
36 * 1. 当用户调用refer()所返回的Invoker对象的invoke()方法时,协议需相应执行同URL远端export()传入的Invoker对象的invoke()方法。
37 * 2. refer()返回的Invoker由协议实现,协议通常需要在此Invoker中发送远程请求。
38 * 3. 当url中有设置check=false时,连接失败不能抛出异常,并内部自动恢复。
39 *40 * @param
服务的类型41 * @param type 服务的类型42 * @param url 远程服务的URL地址43 * @return invoker 服务的本地代理44 * @throws RpcException 当连接服务提供方失败时抛出45 */46 @Adaptive47
Invoker
refer(Class
type, URL url) throws RpcException;48 49 /**50 * 释放协议:
51 * 1. 取消该协议所有已经暴露和引用的服务。
52 * 2. 释放协议所占用的所有资源,比如连接和端口。
53 * 3. 协议在释放后,依然能暴露和引用新的服务。
54 */55 void destroy();56 }

注意:这里有两个核心注解

  • @SPI:指定一个接口为SPI接口(可扩展接口)
    1 @Documented2 @Retention(RetentionPolicy.RUNTIME)3 @Target({ElementType.TYPE})4 public @interface SPI {5     /** 缺省扩展点名 */6     String value() default "";7 }

     

  • @Adaptive该注解可以注解在两个地方:

    • 接口上:例如AdaptiveExtensionFactory(该类不是工厂类,有特殊的逻辑)  AdaptiveCompiler(实际上也是工厂类,但是不能靠动态生成,否则会形成死循环)
    • 接口的方法上:会动态生成相应的动态类(实际上是一个工厂类,工厂设计模式),例如Protocol$Adapter

这个接口极其重要,后续的整个服务暴露和服务调用会用到该接口的两个方法。

 

二 获取ExtensionLoader

1 ExtensionLoader
loader = ExtensionLoader.getExtensionLoader(Protocol.class);

ExtensionLoader可以类比为JDK-SPI中的ServiceLoader

首先来看一下ExtensionLoader的类属性:

1     /** 存放SPI文件的三个目录,其中META-INF/services/也是jdk的SPI文件的存放目录 */ 2     private static final String SERVICES_DIRECTORY = "META-INF/services/"; 3     private static final String DUBBO_DIRECTORY = "META-INF/dubbo/"; 4     private static final String DUBBO_INTERNAL_DIRECTORY = DUBBO_DIRECTORY + "internal/";//这个是最终jar包中存放spi文件的位置 5  6     private static final Pattern NAME_SEPARATOR = Pattern.compile("\\s*[,]+\\s*"); 7     /** key: SPI接口Class value: 该接口的ExtensionLoader */ 8     private static final ConcurrentMap
, ExtensionLoader
> EXTENSION_LOADERS = new ConcurrentHashMap
, ExtensionLoader
>(); 9 /** key: SPI接口Class value: SPI实现类的对象实例 */10 private static final ConcurrentMap
, Object> EXTENSION_INSTANCES = new ConcurrentHashMap
, Object>();

注意:上述的都是类属性,即所有该类的实例都共享。而后边的实例属性就属于每一个类的实例私有

再来看一下ExtensionLoader的实例属性:

1     /** SPI接口Class */ 2     private final Class
type; 3 /** SPI实现类对象实例的创建工厂 */ 4 private final ExtensionFactory objectFactory; 5 /** key: ExtensionClass的Class value: SPI实现类的key */ 6 private final ConcurrentMap
, String> cachedNames = new ConcurrentHashMap
, String>(); 7 /** 存放所有的extensionClass */ 8 private final Holder
>> cachedClasses = new Holder
>>(); 9 10 private final Map
cachedActivates = new ConcurrentHashMap
();11 /** 缓存创建好的extensionClass实例 */12 private final ConcurrentMap
> cachedInstances = new ConcurrentHashMap
>();13 /** 缓存创建好的适配类实例 */14 private final Holder
cachedAdaptiveInstance = new Holder();15 /** 存储类上带有@Adaptive注解的Class */16 private volatile Class
cachedAdaptiveClass = null;17 /** 默认的SPI文件中的key */18 private String cachedDefaultName;19 /** 存储在创建适配类实例这个过程中发生的错误 */20 private volatile Throwable createAdaptiveInstanceError;21 /** 存放具有一个type入参的构造器的实现类的Class对象 */22 private Set
> cachedWrapperClasses;23 /** key :实现类的全类名 value: exception, 防止真正的异常被吞掉 */24 private Map
exceptions = new ConcurrentHashMap
();

来看一下getExtensionLoader(Class<T> type)的源码:

1     /** 2      * 1 校验入参type:非空 + 接口 + 含有@SPI注解 3      * 2 根据type接口从全局缓存EXTENSION_LOADERS中获取ExtensionLoader,如果有直接返回;如果没有,则先创建,之后放入缓存,最后返回 4      */ 5     public static 
ExtensionLoader
getExtensionLoader(Class
type) { 6 if (type == null) 7 throw new IllegalArgumentException("Extension type == null"); 8 if (!type.isInterface()) { 9 throw new IllegalArgumentException("Extension type(" + type + ") is not interface!");10 }11 if (!withExtensionAnnotation(type)) {12 throw new IllegalArgumentException("Extension type(" + type +13 ") is not extension, because WITHOUT @" + SPI.class.getSimpleName() + " Annotation!");14 }15 16 ExtensionLoader
loader = (ExtensionLoader
) EXTENSION_LOADERS.get(type);17 if (loader == null) {18 EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader
(type));19 loader = (ExtensionLoader
) EXTENSION_LOADERS.get(type);20 }21 return loader;22 }

创建ExtensionLoader:

1     private ExtensionLoader(Class
type) {2 this.type = type;3 objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());4 }

当前创建的ExtensionLoader对象(我们取名为ExtensionLoader对象1)的type是com.alibaba.dubbo.rpc.Protocol,所以此时会执行:ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()。

首先是创建ExtensionFactory,通过上边核心类部分ExtensionFactory接口的源码可以看出,此类也是一个SPI接口类,且没有指定默认的实现类的key。

1 ExtensionLoader.getExtensionLoader(ExtensionFactory.class)

下面的代码与上述的过程相似,只是此时创建的另外一个ExtensionLoader对象(我们取名为ExtensionLoader对象2)的type是com.alibaba.dubbo.common.extension.ExtensionFactory,而objectFactory是null。之后,这个ExtensionLoader对象2被放入EXTENSION_LOADERS缓存。这里给出ExtensionFactory的定义,该类也极其重要。//TODO

1 package com.alibaba.dubbo.common.extension;2 3 @SPI4 public interface ExtensionFactory {5     
T getExtension(Class
type, String name);6 }

之后执行ExtensionLoader对象2的getAdaptiveExtension()方法。

1     /** 2      * 首先从cachedAdaptiveInstance缓存中获取AdaptiveExtension实例 3      * 如果不为null, 直接返回; 4      * 如果为null, 先创建AdaptiveExtension实例, 之后放入cachedAdaptiveInstance缓存中,最后返回 5      */ 6     public T getAdaptiveExtension() { 7         Object instance = cachedAdaptiveInstance.get(); 8         if (instance == null) { 9             if (createAdaptiveInstanceError == null) {10                 synchronized (cachedAdaptiveInstance) {11                     instance = cachedAdaptiveInstance.get();12                     if (instance == null) {13                         try {14                             instance = createAdaptiveExtension();15                             cachedAdaptiveInstance.set(instance);16                         } catch (Throwable t) {17                             createAdaptiveInstanceError = t;18                             throw new IllegalStateException("fail to create adaptive instance: " + t.toString(), t);19                         }20                     }21                 }22             } else {23                 throw new IllegalStateException("fail to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError);24             }25         }26 27         return (T) instance;28     }

来看createAdaptiveExtension()创建AdaptiveExtension的源码:

1     /** 2      * createAdaptiveExtension() 3      * --getAdaptiveExtensionClass() 4      *   //从dubbo-spi配置文件中获取AdaptiveExtensionClass 5      *   --getExtensionClasses() 6      *     --loadExtensionClasses() 7      *       --loadFile(Map
> extensionClasses, String dir) 8 * //创建动态代理类 9 * --createAdaptiveExtensionClass()10 *11 * --injectExtension(T instance) //dubbo-ioc12 */13 private T createAdaptiveExtension() {14 try {15 return injectExtension((T) getAdaptiveExtensionClass().newInstance());16 } catch (Exception e) {17 throw new IllegalStateException("Can not create adaptive extenstion " + type + ", cause: " + e.getMessage(), e);18 }19 }

调用层级看注释。injectExtension(T instance)方法只对objectFactory有用,如果objectFactory==null,则直接返回T instance。所以这里返回的是getAdaptiveExtensionClass().newInstance()

来看getAdaptiveExtensionClass()的源码:

1     /** 2      * 获取ExtensionClasses和适配类 3      * 如果实现类上带有@Adaptive注解,直接创建修饰类 4      * 如果方法上带有@Adaptive注解,动态生成代理类 5      */ 6     private Class
getAdaptiveExtensionClass() { 7 getExtensionClasses(); 8 if (cachedAdaptiveClass != null) { 9 return cachedAdaptiveClass;10 }11 return cachedAdaptiveClass = createAdaptiveExtensionClass();12 }

现在来看getExtensionClasses():

1     /** 2      * 先从cachedClasses缓存中获取所有的ExtensionClass,如果有,直接返回; 3      * 如果没有,通过loadExtensionClasses()从SPI文件中去读取,之后写入缓存 4      */ 5     private Map
> getExtensionClasses() { 6 Map
> classes = cachedClasses.get(); 7 if (classes == null) { 8 synchronized (cachedClasses) { 9 classes = cachedClasses.get();10 if (classes == null) {11 classes = loadExtensionClasses();12 cachedClasses.set(classes);13 }14 }15 }16 return classes;17 }

现在来看loadExtensionClasses()

1     /** 2      * 1 从@SPI注解中将默认值解析出来,并缓存到cachedDefaultName中 3      * 2 从SPI文件中获取extensionClass并存储到extensionClasses中,最后返回extensionClasses 4      * 注意:此方法已经getExtensionClasses方法同步过。 5      */ 6     private Map
> loadExtensionClasses() { 7 final SPI defaultAnnotation = type.getAnnotation(SPI.class); 8 if (defaultAnnotation != null) { 9 String value = defaultAnnotation.value();10 if (value != null && (value = value.trim()).length() > 0) {11 String[] names = NAME_SEPARATOR.split(value);12 if (names.length > 1) {13 throw new IllegalStateException("more than 1 default extension name on extension " + type.getName()14 + ": " + Arrays.toString(names));15 }16 if (names.length == 1) cachedDefaultName = names[0];17 }18 }19 20 Map
> extensionClasses = new HashMap
>();21 loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY);22 loadFile(extensionClasses, DUBBO_DIRECTORY);23 loadFile(extensionClasses, SERVICES_DIRECTORY);24 return extensionClasses;25 }

之后来看一下非常重要的一个方法loadFile(Map<String, Class<?>> extensionClasses, String dir)。

1     /**  2      * 1 加载dir目录下的指定type名称的文件(例如:dubbo-2.5.5.jar中的/META-INF/dubbo/internal/com.alibaba.dubbo.common.extension.ExtensionFactory)  3      * 2 遍历该文件中的每一行  4      * (1)获取实现类key和value, 例如 name=spi, line=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory  5      * (2)根据line创建Class对象  6      * (3)将具有@Adaptive注解的实现类的Class对象放在cachedAdaptiveClass缓存中, 注意该缓存只能存放一个具有@Adaptive注解的实现类的Class对象,如果有两个满足条件,则抛异常  7      * 下面的都是对不含@Adaptive注解的实现类的Class对象:  8      * (4)查看是否具有含有一个type入参的构造器, 如果有(就是wrapper类), 将当前的Class对象放置到cachedWrapperClasses缓存中  9      * (5)如果没有含有一个type入参的构造器, 获取无参构造器. 如果Class对象具有@Active注解, 将该对象以
<实现类的key, active>
存储起来 10 * (6)最后,将
存入cachedNames缓存,并将这些Class存入extensionClasses中. 11 * @param extensionClasses 12 * @param dir 13 */ 14 private void loadFile(Map
> extensionClasses, String dir) { 15 String fileName = dir + type.getName(); 16 try { 17 Enumeration
urls; 18 ClassLoader classLoader = findClassLoader(); 19 if (classLoader != null) { 20 urls = classLoader.getResources(fileName); 21 } else { 22 urls = ClassLoader.getSystemResources(fileName); 23 } 24 if (urls != null) { 25 while (urls.hasMoreElements()) { 26 java.net.URL url = urls.nextElement(); 27 try { 28 BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream(), "utf-8")); 29 try { 30 String line = null; 31 while ((line = reader.readLine()) != null) { 32 final int ci = line.indexOf('#'); 33 if (ci >= 0) line = line.substring(0, ci); 34 line = line.trim(); 35 if (line.length() > 0) { 36 try { 37 String name = null; 38 int i = line.indexOf('='); 39 if (i > 0) { 40 name = line.substring(0, i).trim(); 41 line = line.substring(i + 1).trim(); 42 } 43 if (line.length() > 0) { 44 Class
clazz = Class.forName(line, true, classLoader); 45 if (!type.isAssignableFrom(clazz)) { 46 throw new IllegalStateException("Error when load extension class(interface: " + 47 type + ", class line: " + clazz.getName() + "), class " 48 + clazz.getName() + "is not subtype of interface."); 49 } 50 if (clazz.isAnnotationPresent(Adaptive.class)) { 51 if (cachedAdaptiveClass == null) { 52 cachedAdaptiveClass = clazz; 53 } else if (!cachedAdaptiveClass.equals(clazz)) { 54 throw new IllegalStateException("More than 1 adaptive class found: " 55 + cachedAdaptiveClass.getClass().getName() 56 + ", " + clazz.getClass().getName()); 57 } 58 } else { 59 try { 60 clazz.getConstructor(type); 61 Set
> wrappers = cachedWrapperClasses; 62 if (wrappers == null) { 63 cachedWrapperClasses = new ConcurrentHashSet
>(); 64 wrappers = cachedWrapperClasses; 65 } 66 wrappers.add(clazz); 67 } catch (NoSuchMethodException e) { 68 clazz.getConstructor(); 69 if (name == null || name.length() == 0) { 70 name = findAnnotationName(clazz); 71 if (name == null || name.length() == 0) { 72 if (clazz.getSimpleName().length() > type.getSimpleName().length() 73 && clazz.getSimpleName().endsWith(type.getSimpleName())) { 74 name = clazz.getSimpleName().substring(0, clazz.getSimpleName().length() - type.getSimpleName().length()).toLowerCase(); 75 } else { 76 throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + url); 77 } 78 } 79 } 80 String[] names = NAME_SEPARATOR.split(name); 81 if (names != null && names.length > 0) { 82 Activate activate = clazz.getAnnotation(Activate.class); 83 if (activate != null) { 84 cachedActivates.put(names[0], activate); 85 } 86 for (String n : names) { 87 if (!cachedNames.containsKey(clazz)) { 88 cachedNames.put(clazz, n); 89 } 90 Class
c = extensionClasses.get(n); 91 if (c == null) { 92 extensionClasses.put(n, clazz); 93 } else if (c != clazz) { 94 throw new IllegalStateException("Duplicate extension " + type.getName() + " name " + n + " on " + c.getName() + " and " + clazz.getName()); 95 } 96 } 97 } 98 } 99 }100 }101 } catch (Throwable t) {102 IllegalStateException e = new IllegalStateException("Failed to load extension class(interface: " + type + ", class line: " + line + ") in " + url + ", cause: " + t.getMessage(), t);103 exceptions.put(line, e);104 }105 }106 } // end of while read lines107 } finally {108 reader.close();109 }110 } catch (Throwable t) {111 logger.error("Exception when load extension class(interface: " +112 type + ", class file: " + url + ") in " + url, t);113 }114 } // end of while urls115 }116 } catch (Throwable t) {117 logger.error("Exception when load extension class(interface: " +118 type + ", description file: " + fileName + ").", t);119 }120 }

上述的方法分别从三个目录查找SPI文件并进行加载。在这里只有在META-INF/dubbo/internal/com.alibaba.dubbo.common.extension.ExtensionFactory中有值,内容如下:

1 adaptive=com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory2 spi=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory3 spring=com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory

其中AdaptiveExtensionFactory在类上具有@Adaptive注解,这个类会在后续去讲,这里先略过。

执行过后,看一下:

  • cachedAdaptiveClass=class com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory
  • extensionClasses=[{"spring","class com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory"}, {"spi", "class com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory"}],后续会这个集合存储在cachedClasses缓存中。

上边一直在讲解getAdaptiveExtensionClass().newInstance()这句代码中的getAdaptiveExtensionClass(),此方法返回一个com.alibaba.dubbo.common.extension.factory.AdaptiveExtensionFactory类,之后来看一下其newInstance()代码,调用这个方法,默认会执行AdaptiveExtensionFactory的无参构造器。这里给出AdaptiveExtensionFactory的完整代码:

1 package com.alibaba.dubbo.common.extension.factory; 2  3 import com.alibaba.dubbo.common.extension.Adaptive; 4 import com.alibaba.dubbo.common.extension.ExtensionFactory; 5 import com.alibaba.dubbo.common.extension.ExtensionLoader; 6  7 import java.util.ArrayList; 8 import java.util.Collections; 9 import java.util.List;10 11 /**12  * AdaptiveExtensionFactory13  */14 @Adaptive15 public class AdaptiveExtensionFactory implements ExtensionFactory {16     private final List
factories;17 18 /**19 * 遍历cachedClasses中缓存的extensionClasses的key,之后根据key来实例化对应的实现类,最后放置到EXTENSION_INSTANCES缓存中20 */21 public AdaptiveExtensionFactory() {22 ExtensionLoader
loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);23 List
list = new ArrayList
();24 for (String name : loader.getSupportedExtensions()) {25 list.add(loader.getExtension(name));26 }27 factories = Collections.unmodifiableList(list);28 }29 30 public
T getExtension(Class
type, String name) {31 for (ExtensionFactory factory : factories) {32 T extension = factory.getExtension(type, name);33 if (extension != null) {34 return extension;35 }36 }37 return null;38 }39 }

从上可以看出,这个装饰类只是实例化好了各个ExtensionFactory(这里是SpiExtensionFactory和SpringExtensionFactory),后续通过工厂获取实现类实例都是由具体工厂来完成。

来看一下实例化代码的地方,即loader.getExtension(name):

1     /** 2      * 从cachedInstances缓存中获取name对应的实例,如果没有,通过createExtension(name)创建,之后放入缓存 3      * getExtension(String name) 4      * --createExtension(String name) 5      * ----injectExtension(T instance) 6      */ 7     public T getExtension(String name) { 8         if (name == null || name.length() == 0) 9             throw new IllegalArgumentException("Extension name == null");10         if ("true".equals(name)) {11             return getDefaultExtension();12         }13         Holder holder = cachedInstances.get(name);14         if (holder == null) {15             cachedInstances.putIfAbsent(name, new Holder());16             holder = cachedInstances.get(name);17         }18         Object instance = holder.get();19         if (instance == null) {20             synchronized (holder) {21                 instance = holder.get();22                 if (instance == null) {23                     instance = createExtension(name);24                     holder.set(instance);25                 }26             }27         }28         return (T) instance;29     }

来看一下创建createExtension(name):

1     private T createExtension(String name) { 2         /** 从cachedClasses缓存中获取所有的实现类map,之后通过name获取到对应的实现类的Class对象 */ 3         Class
clazz = getExtensionClasses().get(name); 4 if (clazz == null) { 5 throw findException(name); 6 } 7 try { 8 /** 从EXTENSION_INSTANCES缓存中获取对应的实现类的Class对象,如果没有,直接创建,之后放入缓存 */ 9 T instance = (T) EXTENSION_INSTANCES.get(clazz);10 if (instance == null) {11 EXTENSION_INSTANCES.putIfAbsent(clazz, (T) clazz.newInstance());12 instance = (T) EXTENSION_INSTANCES.get(clazz);13 }14 injectExtension(instance);//ioc15 Set
> wrapperClasses = cachedWrapperClasses;16 if (wrapperClasses != null && wrapperClasses.size() > 0) {17 for (Class
wrapperClass : wrapperClasses) {18 instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));19 }20 }21 return instance;22 } catch (Throwable t) {23 throw new IllegalStateException("Extension instance(name: " + name + ", class: " +24 type + ") could not be instantiated: " + t.getMessage(), t);25 }26 }

这里,就体现出来了dubbo-SPI比JDK-SPI的好处:dubbo-SPI不需要遍历所有的实现类来获取想要的实现类,可以直接通过name来获取。

injectExtension(instance)和wrapper包装功能后续再说。

 

到此为止,ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class);这行代码的整个源码就讲述完成了。最后来看一下整个代码的执行结果。

类变量

  • ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS
    • "interface com.alibaba.dubbo.rpc.Protocol" -> "com.alibaba.dubbo.common.extension.ExtensionLoader[com.alibaba.dubbo.rpc.Protocol]"
    • "interface com.alibaba.dubbo.common.extension.ExtensionFactory" -> "com.alibaba.dubbo.common.extension.ExtensionLoader[com.alibaba.dubbo.common.extension.ExtensionFactory]"
  • ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES
    • "class com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory" -> SpringExtensionFactory实例
    • "class com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory" -> SpiExtensionFactory实例

ExtensionLoader<Protocol> loader的实例变量

  • Class<?> type = interface com.alibaba.dubbo.rpc.Protocol
  • ExtensionFactory objectFactory = AdaptiveExtensionFactory(适配类)
    • factories = [SpringExtensionFactory实例, SpiExtensionFactory实例]

总结:

第一点:ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(Class<T> type)最终得到的实例变量是:

  • Class<?> type = interface T
  • ExtensionFactory objectFactory = AdaptiveExtensionFactory(适配类)
    • factories = [SpringExtensionFactory实例, SpiExtensionFactory实例]

第二点:ExtensionLoader<T>.getAdaptiveExtension()的调用层级

1 ExtensionLoader
.getAdaptiveExtension()2 --createAdaptiveExtension()3 ----injectExtension(getAdaptiveExtensionClass())4 ------getAdaptiveExtensionClass()5 --------getExtensionClasses()//从spi文件中查找实现类上具有@Adaptive注解的类6 ----------loadExtensionClasses()7 ------------loadFile(Map
> extensionClasses, String dir)8 --------createAdaptiveExtensionClass()//如果从spi文件中没有找到实现类上具有@Adaptive注解的类,则动态创建类

最终返回的是创建好的Adaptive类,例如AdaptiveExtensionFactory实例。

第三点:ExtensionLoader<T>.getExtension()的调用层级

1 ExtensionLoader
.getExtension()2 --createExtension(String name)3 ----getExtensionClasses().get(name)//获取扩展类4 ----injectExtension(instance);//ioc5 ----wrapper包装;//aop

最终返回的是创建好的具体实现类,例如SpringExtensionFactory实例。 

 

至此,dubbo-spi源码解析完成!!!

转载地址:http://omzwo.baihongyu.com/

你可能感兴趣的文章
ECS主动运维2.0,体验升级,事半功倍
查看>>
vim 学习方法
查看>>
php token验证范例
查看>>
WebSocket的C++服务器端实现
查看>>
java中两种添加监听器的策略
查看>>
脑洞成现实!AI系统可提前10s预测地震
查看>>
oracle数据库的启动和停止
查看>>
《LoadRunner没有告诉你的》之七——使用 LoadRunner 连续长时间执行测试,如何保证参数化的数据足够又不会重复?...
查看>>
python easy_install django 安装
查看>>
读《图解HTTP》总结--第六章
查看>>
毕业就能拿到上万薪资的程序员他们都做了啥?
查看>>
最小的k个数
查看>>
iOS技巧之获取本机通讯录中的内容,解析通讯录源代码
查看>>
程序员从零到月薪15K的转变,python200G资料分享
查看>>
DNS域名解析的知识了解
查看>>
部署社交网站
查看>>
CentOS下如何修改主机名
查看>>
“机器人商店”是什么?卖机器人的吗?
查看>>
SVN的代码正确提交方法
查看>>
js框架 vue
查看>>