Dubbo-SPI原理
官网地址:https://dubbo.apache.org/zh/docs/v2.7/dev/source/dubbo-spi/
双亲委托模式的弊端
判断类是否加载的时候,应用类加载器会顺着双亲路径往上判断,直到启动类加载器.但是启动类加载器不会往下询问,这个委托路线是单向的,即顶层的类加载器,无法访问底层的类加载器所加载的类
启动类加载器中的类为系统的核心类,比如,在系统类中,提供了一个接口,并且该接口还提供了一个工厂方法用于创建该接口的实例,但是该接口的实现类在应用层中,接口和工厂方法在启动类加载器中,就会出现工厂方法无法创建由应用类加载器加载的应用实例问题.
拥有这样问题的组件有很多,比如JDBC(DataSource、Driver)、Xml parser等.JDBC本身是java连接数据库的一个标准,是进行数据库连接的抽象层,由java编写的一组类和接口组成,接口的实现由各个数据库厂商来完成
文件内容com.mysql.cj.jdbc.Driver
双亲委托模式的补充
在Java中,把核心类(rt.jar)中提供外部服务,可由应用层自行实现的接口,这种方式成为spi
ExtensionLoader
org.apache.dubbo.common.extension.ExtensionLoader#getExtension源码分析
public T getExtension(String name) { // 默认包装成Wrapper对象 return getExtension(name, true); } public T getExtension(String name, boolean wrap) { if (StringUtils.isEmpty(name)) { throw new IllegalArgumentException("Extension name == null"); } // 返回默认的扩展实现类 if ("true".equals(name)) { return getDefaultExtension(); } // volatile + synchronized + double-check 获取或创建扩展点实现类 final Holder<Object> holder = getOrCreateHolder(name); Object instance = holder.get(); if (instance == null) { synchronized (holder) { instance = holder.get(); if (instance == null) { instance = createExtension(name, wrap); holder.set(instance); } } } return (T) instance; }
createExtension源码分析
private T createExtension(String name, boolean wrap) { // 从配置文件中加载所有的拓展类,可得到“配置项名称”到“配置类”的映射关系表 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, clazz.newInstance()); instance = (T) EXTENSION_INSTANCES.get(clazz); } // 向实例中注入依赖,为变量赋值 injectExtension(instance); if (wrap) { List<Class<?>> wrapperClassesList = new ArrayList<>(); if (cachedWrapperClasses != null) { wrapperClassesList.addAll(cachedWrapperClasses);
// 根据Activate注解中的order属性值排序 wrapperClassesList.sort(WrapperComparator.COMPARATOR); Collections.reverse(wrapperClassesList); } // 循环创建 Wrapper 实例 if (CollectionUtils.isNotEmpty(wrapperClassesList)) { for (Class<?> wrapperClass : wrapperClassesList) { Wrapper wrapper = wrapperClass.getAnnotation(Wrapper.class); if (wrapper == null || (ArrayUtils.contains(wrapper.matches(), name) && !ArrayUtils.contains(wrapper.mismatches(), name))) { // 将当前 instance 作为参数传给 Wrapper 的构造方法,并通过反射创建 Wrapper 实例 // 然后向 Wrapper 实例中注入依赖,最后将 Wrapper 实例再次赋值给 instance 变量 instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)); } } } } // 是否实现了 Lifecycle,生命周期的初始化处理 initExtension(instance); return instance; } catch (Throwable t) { throw new IllegalStateException("Extension instance (name: " + name + ", class: " + type + ") couldn't be instantiated: " + t.getMessage(), t); } }
getExtensionClasses源码分析
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; }
loadExtensionClasses源码分析
private Map<String, Class<?>> loadExtensionClasses() { // 对 SPI 注解进行解析,如果存在默认扩展名则获取并缓存 cacheDefaultExtensionName(); Map<String, Class<?>> extensionClasses = new HashMap<>(); // 根据加载策略加载指定文件夹下的配置文件 for (LoadingStrategy strategy : strategies) { loadDirectory(extensionClasses, strategy.directory(), type.getName(), strategy.preferExtensionClassLoader(), strategy.overridden(), strategy.excludedPackages()); loadDirectory(extensionClasses, strategy.directory(), type.getName().replace("org.apache", "com.alibaba"), strategy.preferExtensionClassLoader(), strategy.overridden(), strategy.excludedPackages()); } return extensionClasses; } private void cacheDefaultExtensionName() { // 获取 SPI 注解,这里的 type 变量是在调用 getExtensionLoader 方法时传入的 final SPI defaultAnnotation = type.getAnnotation(SPI.class); if (defaultAnnotation == null) { return; } String value = defaultAnnotation.value(); if ((value = value.trim()).length() > 0) { // 对 SPI 注解内容进行切分 String[] names = NAME_SEPARATOR.split(value); // 检测 SPI 注解内容是否合法,不合法则抛出异常 if (names.length > 1) { throw new IllegalStateException("More than 1 default extension name on extension " + type.getName() + ": " + Arrays.toString(names)); } // 设置默认名称,参考 getDefaultExtension 方法 if (names.length == 1) { cachedDefaultName = names[0]; } } }
loadDirectory源码分析
private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir, String type, boolean extensionLoaderClassLoaderFirst, boolean overridden, String... excludedPackages) { // fileName = 文件夹路径 + type 全限定名 String fileName = dir + type; try { Enumeration<java.net.URL> urls = null; ClassLoader classLoader = findClassLoader(); // try to load from ExtensionLoader's ClassLoader first if (extensionLoaderClassLoaderFirst) { ClassLoader extensionLoaderClassLoader = ExtensionLoader.class.getClassLoader(); if (ClassLoader.getSystemClassLoader() != extensionLoaderClassLoader) { urls = extensionLoaderClassLoader.getResources(fileName); } } // 根据文件名加载所有的同名文件 if (urls == null || !urls.hasMoreElements()) { if (classLoader != null) { urls = classLoader.getResources(fileName); } else { urls = ClassLoader.getSystemResources(fileName); } } if (urls != null) { while (urls.hasMoreElements()) { java.net.URL resourceURL = urls.nextElement(); // 加载资源 loadResource(extensionClasses, classLoader, resourceURL, overridden, excludedPackages); } } } catch (Throwable t) { logger.error("Exception occurred when loading extension class (interface: " + type + ", description file: " + fileName + ").", t); } }
loadResource源码分析
private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader, java.net.URL resourceURL, boolean overridden, String... excludedPackages) { try { try (BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), StandardCharsets.UTF_8))) { String line; // 按行读取配置内容 while ((line = reader.readLine()) != null) { // 定位 # 字符 final int ci = line.indexOf('#'); if (ci >= 0) { // 截取 # 之前的字符串,# 之后的内容为注释,需要忽略 line = line.substring(0, ci); } line = line.trim(); if (line.length() > 0) { try { String name = null; int i = line.indexOf('='); if (i > 0) { // 以等于号 = 为界,截取键与值 name = line.substring(0, i).trim(); line = line.substring(i + 1).trim(); } if (line.length() > 0 && !isExcluded(line, excludedPackages)) { // 加载类,并通过 loadClass 方法对类进行缓存 loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name, overridden); } } catch (Throwable t) { IllegalStateException e = new IllegalStateException("Failed to load extension class (interface: " + type + ", class line: " + line + ") in " + resourceURL + ", cause: " + t.getMessage(), t); exceptions.put(line, e); } } } } } catch (Throwable t) { logger.error("Exception occurred when loading extension class (interface: " + type + ", class file: " + resourceURL + ") in " + resourceURL, t); } }
loadClass源码分析
private void loadClass(Map<String, Class<?>> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name, boolean overridden) throws NoSuchMethodException { if (!type.isAssignableFrom(clazz)) { throw new IllegalStateException("Error occurred when loading extension class (interface: " + type + ", class line: " + clazz.getName() + "), class " + clazz.getName() + " is not subtype of interface."); } // 检测目标类上是否有 Adaptive 注解 if (clazz.isAnnotationPresent(Adaptive.class)) { // 设置 cachedAdaptiveClass缓存 cacheAdaptiveClass(clazz, overridden); } // 检测 clazz 是否是 Wrapper 类型,判断依据是是否有当前 type 的有参构造器 else if (isWrapperClass(clazz)) { // 存储 clazz 到 cachedWrapperClasses 缓存中 cacheWrapperClass(clazz); } // 程序进入此分支,表明 clazz 是一个普通的拓展类 else { // 检测 clazz 是否有默认的构造方法,如果没有,则抛出异常 clazz.getConstructor(); if (StringUtils.isEmpty(name)) { // 如果 name 为空,则尝试从 Extension 注解中获取 name,或使用小写的类名作为 name name = findAnnotationName(clazz); if (name.length() == 0) { throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + resourceURL); } } // 切分 name String[] names = NAME_SEPARATOR.split(name); if (ArrayUtils.isNotEmpty(names)) { // 如果类上有 Activate 注解,则使用 names 数组的第一个元素作为键, // 存储 name 到 Activate 注解对象的映射关系 cacheActivateClass(clazz, names[0]); for (String n : names) { // 存储 Class 到名称的映射关系 cacheName(clazz, n); // 存储名称到 Class 的映射关系 saveInExtensionClass(extensionClasses, clazz, n, overridden); } } } }
IOC
通过 setter 方法注入依赖,createExtension方法中执行完getExtensionClasses方法,从配置文件中加载完所有的拓展类后,获得了目标扩展实例,进行依赖注入
injectExtension源码分析
private T injectExtension(T instance) { if (objectFactory == null) { return instance; } try { // 遍历目标类的所有方法 for (Method method : instance.getClass().getMethods()) { // 检测方法是否以 set 开头,且方法仅有一个参数,且方法访问级别为 public if (!isSetter(method)) { continue; } /** * Check {@link DisableInject} to see if we need auto injection for this property */ if (method.getAnnotation(DisableInject.class) != null) { continue; } // 获取 setter 方法参数类型 Class<?> pt = method.getParameterTypes()[0]; if (ReflectUtils.isPrimitives(pt)) { continue; } try { // 获取属性名,比如 setName 方法对应属性名 name String property = getSetterProperty(method); // 从 ObjectFactory 中获取依赖对象,SPI方式,Spring方式 Object object = objectFactory.getExtension(pt, property); if (object != null) { // 通过反射调用 setter 方法设置依赖 method.invoke(instance, object); } } catch (Exception e) { logger.error("Failed to inject via method " + method.getName() + " of interface " + type.getName() + ": " + e.getMessage(), e); } } } catch (Exception e) { logger.error(e.getMessage(), e); } return instance; }
AOP
createExtension方法中
if (wrap) { List<Class<?>> wrapperClassesList = new ArrayList<>(); if (cachedWrapperClasses != null) { wrapperClassesList.addAll(cachedWrapperClasses); // 根据Activate注解中的order属性值排序 wrapperClassesList.sort(WrapperComparator.COMPARATOR); Collections.reverse(wrapperClassesList); } // 循环创建 Wrapper 实例 if (CollectionUtils.isNotEmpty(wrapperClassesList)) { for (Class<?> wrapperClass : wrapperClassesList) { Wrapper wrapper = wrapperClass.getAnnotation(Wrapper.class); // Wrapper注解为空,或者不为空但是符合匹配条件 if (wrapper == null || (ArrayUtils.contains(wrapper.matches(), name) && !ArrayUtils.contains(wrapper.mismatches(), name))) { // 将当前 instance 作为参数传给 Wrapper 的构造方法,并通过反射创建 Wrapper 实例,实现了AOP // 然后向 Wrapper 实例中注入依赖,最后将 Wrapper 实例再次赋值给 instance 变量 instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)); } } } }
Adaptive
getAdaptiveExtension源码分析
public T getAdaptiveExtension() { Object instance = cachedAdaptiveInstance.get(); if (instance == null) { // 并发情况下,如果有error直接报错,不去竞争锁了 if (createAdaptiveInstanceError != null) { throw new IllegalStateException("Failed to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError); } synchronized (cachedAdaptiveInstance) { instance = cachedAdaptiveInstance.get(); if (instance == null) { try { // 创建Adaptive实例 instance = createAdaptiveExtension(); cachedAdaptiveInstance.set(instance); } catch (Throwable t) { createAdaptiveInstanceError = t; throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t); } } } } return (T) instance; } private T createAdaptiveExtension() { try { // 获取Adaptive扩展类字节码,反射获取实例 return injectExtension((T) getAdaptiveExtensionClass().newInstance()); } catch (Exception e) { throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e); } } private Class<?> getAdaptiveExtensionClass() { getExtensionClasses(); if (cachedAdaptiveClass != null) { return cachedAdaptiveClass; } // Javassist方式或JDK方式创建Adaptive扩展类字节码 return cachedAdaptiveClass = createAdaptiveExtensionClass(); }
createAdaptiveExtensionClass源码分析
private Class<?> createAdaptiveExtensionClass() { // 创建Adaptive类java代码 String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate(); ClassLoader classLoader = findClassLoader(); org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension(); // 编译Adaptive类java代码,创建Adaptive类字节码获取Adaptive类Class对象 return compiler.compile(code, classLoader); }
AdaptiveClassCodeGenerator#generate源码分析
public String generate() { // no need to generate adaptive class since there's no adaptive method found. if (!hasAdaptiveMethod()) { throw new IllegalStateException("No adaptive method exist on extension " + type.getName() + ", refuse to create the adaptive class!"); } StringBuilder code = new StringBuilder(); // package信息 code.append(generatePackageInfo()); // import信息 code.append(generateImports()); // 类声明信息 public class %s$Adaptive implements %s code.append(generateClassDeclaration()); // 方法信息 Method[] methods = type.getMethods(); for (Method method : methods) { code.append(generateMethod(method)); } code.append("}"); if (logger.isDebugEnabled()) { logger.debug(code.toString()); } return code.toString(); }
java代码结果示例
package org.apache.dubbo.common.extension.adaptive; import org.apache.dubbo.common.extension.ExtensionLoader; public class HasAdaptiveExt$Adaptive implements org.apache.dubbo.common.extension.adaptive.HasAdaptiveExt { public java.lang.String echo(org.apache.dubbo.common.URL arg0, java.lang.String arg1) { if (arg0 == null) throw new IllegalArgumentException("url == null"); org.apache.dubbo.common.URL url = arg0; String extName = url.getParameter("has.adaptive.ext", "adaptive"); if(extName == null) throw new IllegalStateException("Failed to get extension (org.apache.dubbo.common.extension.adaptive.HasAdaptiveExt) name from url (" + url.toString() + ") use keys([has.adaptive.ext])"); org.apache.dubbo.common.extension.adaptive.HasAdaptiveExt extension = (org.apache.dubbo.common.extension.adaptive.HasAdaptiveExt)ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.extension.adaptive.HasAdaptiveExt.class).getExtension(extName); return extension.echo(arg0, arg1); } }
Compiler
利用Javassist、JDK将java代码编译为Class对象