此文已由作者赵计刚薪授权网易云社区发布。
欢迎访问网易云社区,了解更多网易技术产品运营经验。
之后来看一下非常重要的一个方法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注解,这个类会在后续去讲,这里先略过。
执行过后,看一下:
上边一直在讲解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来获取。
injectExtension(instance)和wrapper包装功能后续再说。
到此为止,ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class);这行代码的整个源码就讲述完成了。最后来看一下整个代码的执行结果。
类变量
ExtensionLoader<Protocol> loader的实例变量:
总结:
第一点:ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(Class<T> type)最终得到的实例变量是:
第二点: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实例。
至此,dubbo-spi源码解析完成!!!
更多网易技术、产品、运营经验分享请点击。