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<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class);
9 final Protocol dubboProtocol = loader.getExtension("dubbo");
10 final Protocol adaptiveExtension = loader.getAdaptiveExtension();
11 }
12 }
@SPI:指定一个接口为SPI接口(可扩展接口)
1 @Documented
2 @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<Protocol> 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<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<Class<?>, ExtensionLoader<?>>();
9 /** key: SPI接口Class value: SPI实现类的对象实例 */
10 private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<Class<?>, 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<Class<?>, String> cachedNames = new ConcurrentHashMap<Class<?>, String>();
7 /** 存放所有的extensionClass */
8 private final Holder<Map<String, Class<?>>> cachedClasses = new Holder<Map<String, Class<?>>>();
9
10 private final Map<String, Activate> cachedActivates = new ConcurrentHashMap<String, Activate>();
11 /** 缓存创建好的extensionClass实例 */
12 private final ConcurrentMap<String, Holder<Object>> cachedInstances = new ConcurrentHashMap<String, Holder<Object>>();
13 /** 缓存创建好的适配类实例 */
14 private final Holder<Object> cachedAdaptiveInstance = new Holder<Object>();
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<Class<?>> cachedWrapperClasses;
23 /** key :实现类的全类名 value: exception, 防止真正的异常被吞掉 */
24 private Map<String, IllegalStateException> exceptions = new ConcurrentHashMap<String, IllegalStateException>();
来看一下getExtensionLoader(Class<T> type)的源码:
1 /** 2 * 1 校验入参type:非空 + 接口 + 含有@SPI注解 3 * 2 根据type接口从全局缓存EXTENSION_LOADERS中获取ExtensionLoader,如果有直接返回;如果没有,则先创建,之后放入缓存,最后返回 4 */ 5 public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> 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<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); 17 if (loader == null) { 18 EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type)); 19 loader = (ExtensionLoader<T>) 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 @SPI
4 public interface ExtensionFactory {
5 <T> T getExtension(Class<T> 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<String, Class<?>> extensionClasses, String dir)
8 * //创建动态代理类
9 * --createAdaptiveExtensionClass()
10 *
11 * --injectExtension(T instance) //dubbo-ioc
12 */
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<String, Class<?>> getExtensionClasses() {
6 Map<String, Class<?>> 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<String, Class<?>> 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<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();
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)最后,将<Class对象, 实现类的key>存入cachedNames缓存,并将这些Class存入extensionClasses中.
11 * @param extensionClasses
12 * @param dir
13 */
14 private void loadFile(Map<String, Class<?>> extensionClasses, String dir) {
15 String fileName = dir + type.getName();
16 try {
17 Enumeration<java.net.URL> 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<Class<?>> wrappers = cachedWrapperClasses;
62 if (wrappers == null) {
63 cachedWrapperClasses = new ConcurrentHashSet<Class<?>>();
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 lines
107 } 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 urls
115 }
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.AdaptiveExtensionFactory
2 spi=com.alibaba.dubbo.common.extension.factory.SpiExtensionFactory
3 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 * AdaptiveExtensionFactory
13 */
14 @Adaptive
15 public class AdaptiveExtensionFactory implements ExtensionFactory {
16 private final List<ExtensionFactory> factories;
17
18 /**
19 * 遍历cachedClasses中缓存的extensionClasses的key,之后根据key来实例化对应的实现类,最后放置到EXTENSION_INSTANCES缓存中
20 */
21 public AdaptiveExtensionFactory() {
22 ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
23 List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();
24 for (String name : loader.getSupportedExtensions()) {
25 list.add(loader.getExtension(name));
26 }
27 factories = Collections.unmodifiableList(list);
28 }
29
30 public <T> T getExtension(Class<T> 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<Object> holder = cachedInstances.get(name);
14 if (holder == null) {
15 cachedInstances.putIfAbsent(name, new Holder<Object>());
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);//ioc
15 Set<Class<?>> 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来获取。
总结:
第一点:ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(Class<T> type)最终得到的实例变量是:
- Class<?> type = interface T
- ExtensionFactory objectFactory = AdaptiveExtensionFactory(适配类)
- factories = [SpringExtensionFactory实例, SpiExtensionFactory实例]
第二点:ExtensionLoader<T>.getAdaptiveExtension()的调用层级
1 ExtensionLoader<T>.getAdaptiveExtension()
2 --createAdaptiveExtension()
3 ----injectExtension(getAdaptiveExtensionClass())
4 ------getAdaptiveExtensionClass()
5 --------getExtensionClasses()//从spi文件中查找实现类上具有@Adaptive注解的类
6 ----------loadExtensionClasses()
7 ------------loadFile(Map<String, Class<?>> extensionClasses, String dir)
8 --------createAdaptiveExtensionClass()//如果从spi文件中没有找到实现类上具有@Adaptive注解的类,则动态创建类
最终返回的是创建好的Adaptive类,例如AdaptiveExtensionFactory实例。
第三点:ExtensionLoader<T>.getExtension()的调用层级
1 ExtensionLoader<T>.getExtension()
2 --createExtension(String name)
3 ----getExtensionClasses().get(name)//获取扩展类
4 ----injectExtension(instance);//ioc
5 ----wrapper包装;//aop
最终返回的是创建好的具体实现类,例如SpringExtensionFactory实例。