基于Java的SPI机制,Dubbo在其思想的基础上自己实现了一套SPI机制,弥补了Java SPI的缺点,并进行了相应的扩展。
Java SPI
是一次性加载、实例化所有的扩展点实现,不支持根据key
值去加载、实例化指定的扩展点实现。Java SPI
不支持IOC、AOP
,Dubbo SPI
则通过自动包装、自动装配等特性实现了IOC、AOP
。ServerLoader
在加载类的过程中如果出现异常无法加载没有相关的异常抛出,导致一旦出现问题需要花时间进行定位。基于装饰器设计模式,通过创建、配置Wrapper类,从而实现对实现类的增强。我们可以将一些公共的逻辑放置在Wrapper类中,从而实现了公共逻辑与业务逻辑的解耦,同时也更易于扩展和维护。
类似于Spring的IOC依赖注入的功能,在加载扩展点的实现类时,会遍历所有setter方法,尝试着为其注入其他扩展点依赖。
Dubbo使用URL对象传递配置信息,通过在URL对象中配置对应的key-value键值对,从而实现在调用相应方法时能够通过URL中的配置匹配对应的扩展点实现。
当我们想通过一个配置激活多个扩展点实现时,可以通过@Activate注解来实现,从而简化了配置。
package com.dubbo.service; import org.apache.dubbo.common.extension.SPI; @SPI public interface ICarService { void speed(); }
AudiService
、BmwService
package com.dubbo.service.impl; import com.dubbo.service.ICarService; public class AudiService implements ICarService { @Override public void speed() { System.out.println("audi drive speed 100KM/H"); } } public class BMWService implements ICarService { @Override public void speed() { System.out.println("bmw drive speed 200KM/H"); } }
resources\META-INF\services\com.dubbo.service.ICarService
audi=com.dubbo.service.impl.AudiService bmw=com.dubbo.service.impl.BMWService
private static void dubboSpi() { ExtensionLoader<ICarService> extensionLoader = ExtensionLoader.getExtensionLoader(ICarService.class); ICarService carService = extensionLoader.getExtension("audi"); carService.speed(); } // 输出 audi drive speed 100KM/H
Main方法
ExtensionLoader.getExtensionLoader(ICarService.class); ICarService carService = extensionLoader.getExtension("audi");
org.apache.dubbo.common.extension.ExtensionLoader
// key:扩展点接口-扩展点加载器 private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<>(); // 获取扩展点加载器 public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) { ... // 尝试从缓存中获取扩展点加载器 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; }
获取到扩展点加载器后,调用扩展点加载器的getExtension
方法获取扩展点实现对象
public T getExtension(String name) { if (StringUtils.isEmpty(name)) { throw new IllegalArgumentException("Extension name == null"); } // 如果传入name为true,则获取默认扩展实现 if ("true".equals(name)) { return getDefaultExtension(); } // 获取实现类实例持有器,如果没有则创建一个 final Holder<Object> holder = getOrCreateHolder(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; }
先从缓存中获取扩展点实现实例,如果没有获取到则调用createExtension()
进行创建
private T createExtension(String name) { // 获取扩展点实现类(这里下面会详细说下) 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); // 如果有包装类,则递归创建包装类实例,并将当前实例注入包装类实例中 Set<Class<?>> wrapperClasses = cachedWrapperClasses; if (CollectionUtils.isNotEmpty(wrapperClasses)) { for (Class<?> wrapperClass : wrapperClasses) { instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)); } } // 如果是Lifecycle的实现类,则调用initialize()方法 initExtension(instance); return instance; } catch (Throwable t) { throw new IllegalStateException("Extension instance (name: " + name + ", class: " + type + ") couldn't be instantiated: " + t.getMessage(), t); } }
getExtensionClasses()
源码解析,加载指定路径下实现点文件中的别名与实现类Java SPI
会扫描META-INF/services/
目录下的文件从而检测扩展点实现类,Dubbo SPI
该步骤是在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; }
加载META-INF/dubbo/internal/
、META-INF/dubbo/
、META-INF/services/
目录下该扩展点文件中的别名与对应的实现类,放入到缓存Map中,并返回
private Map<String, Class<?>> loadExtensionClasses() { // 缓存当前扩展点的默认实现 cacheDefaultExtensionName(); Map<String, Class<?>> extensionClasses = new HashMap<>(); // 加载 META-INF/dubbo/internal/ 目录下当前扩展点对应的具体实现类列表 (下面会详说) loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName(), true); loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName().replace("org.apache", "com.alibaba"), true); // 加载 META-INF/dubbo/ 目录下当前扩展点对应的具体实现类列表 loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName()); loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName().replace("org.apache", "com.alibaba")); // 加载 META-INF/services/ 目录下当前扩展点对应的具体实现类列表 loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName()); loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName().replace("org.apache", "com.alibaba")); // 返回别名-扩展点实现类Map,这里如果别名一致会覆盖,后来的会覆盖前面的 return extensionClasses; }
loadDirectory()
方法中,会通过类加载器加载扩展点文件,并解析其中的内容,存入extensionClasses Map缓存中
private void loadDirectory(Map<String, Class<?>> extensionClasses, String dir, String type, boolean extensionLoaderClassLoaderFirst) { // 获取文件全路径名 String fileName = dir + type; try { Enumeration<java.net.URL> urls = null; // 获取加载ExtensionLoader类的类加载器 ClassLoader classLoader = findClassLoader(); // 如果是第一次加载,则获取类加载器 if (extensionLoaderClassLoaderFirst) { // 获取加载ExtensionLoader类的类加载器 ClassLoader extensionLoaderClassLoader = ExtensionLoader.class.getClassLoader(); // 如果当前系统的类加载器不是加载ExtensionLoader类的类加载器时,则通过加载ExtensionLoader类的类加载器获取文件对应的url访问路径列表 if (ClassLoader.getSystemClassLoader() != extensionLoaderClassLoader) { urls = extensionLoaderClassLoader.getResources(fileName); } } // 如果urls为空 if(urls == null || !urls.hasMoreElements()) { if (classLoader != null) { // 加载文件对应的url访问路径列表 urls = classLoader.getResources(fileName); } else { // 使用系统类加载器、根类加载器加载文件对应的url访问路径列表 urls = ClassLoader.getSystemResources(fileName); } } if (urls != null) { // 遍历url访问路径列表 while (urls.hasMoreElements()) { java.net.URL resourceURL = urls.nextElement(); // 加载文件内容(下面会详说) loadResource(extensionClasses, classLoader, resourceURL); } } } catch (Throwable t) { logger.error("Exception occurred when loading extension class (interface: " + type + ", description file: " + fileName + ").", t); } }
解析实现点文件,获取别名与对应的实现类全名,加载实现类,放入到extensionClasses
缓存Map中
private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader, java.net.URL resourceURL) { 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 { // 假设 audi=com.lbb.service.impl.AudiService =》则name=audi, line=com.lbb.service.impl.AudiService 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) { // 解析别名、加载实现类,并放入到extensionClasses缓存Map中(下面详说) loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name); } } 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); } }
查看是否存在@Adaptive注解、是否是包装类,如果都不是则解析别名与实现类,放入缓存Map中
private void loadClass(Map<String, Class<?>> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name) 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."); } if (clazz.isAnnotationPresent(Adaptive.class)) { // 如果存在@Adaptive注解,则缓存到cachedAdaptiveClass中 cacheAdaptiveClass(clazz); } else if (isWrapperClass(clazz)) { // 如果这个类的构造方法的参数类型是实现点接口,则说明是包装类,缓存到cachedWrapperClasses List中 cacheWrapperClass(clazz); } else { clazz.getConstructor(); if (StringUtils.isEmpty(name)) { name = findAnnotationName(clazz); if (name.length() == 0) { throw new IllegalStateException("No such extension name for the class " + clazz.getName() + " in the config " + resourceURL); } } // 解析别名,处理分隔符 String[] names = NAME_SEPARATOR.split(name); if (ArrayUtils.isNotEmpty(names)) { // 缓存实现类-别名 cacheActivateClass(clazz, names[0]); for (String n : names) { // 缓存实现类与别名 cacheName(clazz, n); // 缓存别名与实现类到extensionClasses 缓存Map中 saveInExtensionClass(extensionClasses, clazz, n); } } } }
private T injectExtension(T instance) { if (objectFactory == null) { return instance; } try { // 遍历实现类中的所有方法 for (Method method : instance.getClass().getMethods()) { // 如果不是set方法,则继续遍历 if (!isSetter(method)) { continue; } // 如果方法上存在@DisableInject注解,则继续遍历 if (method.getAnnotation(DisableInject.class) != null) { continue; } // 获取set方法的第一个参数的类型 Class<?> pt = method.getParameterTypes()[0]; // 如果该参数类型是基础数据类型,则继续遍历 if (ReflectUtils.isPrimitives(pt)) { continue; } try { // 解析set后的名称,setCarService =》 carService String property = getSetterProperty(method); // 根据解析后的名称去工厂中获取对应的扩展类对象 Object object = objectFactory.getExtension(pt, property); if (object != null) { // 通过反射调用set方法进行注入 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; }
initExtension()
方法的源码,调用实现类对象的初始化方法进行初始化private void initExtension(T instance) { // 检测是否实现了Lifecycle接口 if (instance instanceof Lifecycle) { Lifecycle lifecycle = (Lifecycle) instance; // 如果实现了,则调用其初始化方法 lifecycle.initialize(); } }