-
概述
duobo的SPI机制贯穿于duobbo的整个架构,dubbo架构上是分层的,每层之间是面向接口的,每个接口具体使用哪个实现去提供服务于上层,这个时候就会触发dubbo的SPI机制,dubbo的每层接口都是一个扩展点,这个时候用哪个实现会有一个拓展适配器的东西去根据SPI接口传递的参数实例化具体提供服务的实现类。其实SPI机制还可以理解为文件方式配置的简单工厂模式,拓展适配器就是那个简单工厂。 -
Demo
/** * @author wuxinxin */ @SPI public interface Animal { void say(); } /** * @author wuxinxin */ public class Pig implements Animal { public void say() { System.out.println("猪叫"); } } /** * @author wuxinxin */ public class SpiTest { public static void main(String[] args) { ExtensionLoader<Animal> extensionLoader = ExtensionLoader.getExtensionLoader(Animal.class); Animal pig = extensionLoader.getExtension("pig"); pig.say(); } } //配置文件classpath: META-INF/dubbo/com.example.dubbo.spi.Animal pig = com.example.dubbo.spi.Pig dog = com.example.dubbo.spi.Dog
-
源码分析
功能:创建某个类型的ExtensionLoader对象 private ExtensionLoader(Class<?> type) { this.type = type; //这个objectFactory就是拓展点适配器 objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()); } @SuppressWarnings("unchecked") //静态方法直接调用getExtensionLoader获取某种class的ExtensionLoader对象 public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) { if (type == null) { throw new IllegalArgumentException("Extension type == null"); } if (!type.isInterface()) { throw new IllegalArgumentException("Extension type (" + type + ") is not an interface!"); } if (!withExtensionAnnotation(type)) { throw new IllegalArgumentException("Extension type (" + type + ") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!"); } //EXTENSION_LOADERS是一个<Class<?>, ExtensionLoader<?>>的Map,用作缓存 ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); if (loader == null) { //如果当前类型没有创建ExtensionLoader对象,那么进行创建 EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type)); loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type); } return loader; }
功能:加载拓展点的所有实现(拓展点适配器是一个特殊的实现) public T getAdaptiveExtension() { //cachedAdaptiveInstance是缓存拓展点适配器对象的 Object instance = cachedAdaptiveInstance.get(); if (instance == null) { if (createAdaptiveInstanceError == null) { synchronized (cachedAdaptiveInstance) { instance = cachedAdaptiveInstance.get(); if (instance == null) { try { //如果拓展点适配器对象不存在,那么创建 instance = createAdaptiveExtension(); cachedAdaptiveInstance.set(instance); } catch (Throwable t) { createAdaptiveInstanceError = t; throw new IllegalStateException("Failed to create adaptive instance: " + t.toString(), t); } } } } else { throw new IllegalStateException("Failed to create adaptive instance: " + createAdaptiveInstanceError.toString(), createAdaptiveInstanceError); } } return (T) instance; } //createAdaptiveExtension @SuppressWarnings("unchecked") private T createAdaptiveExtension() { try { //1.获取适配器类型的class对象 //2.获取到class对象后,创建适配器对象 //3.给适配器的set方法进行注入依赖的对象,毕竟适配器对象不是spring管理的,是运行时产生的 return injectExtension((T) getAdaptiveExtensionClass().newInstance()); } catch (Exception e) { throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e); } } //getAdaptiveExtensionClass private Class<?> getAdaptiveExtensionClass() { //获取当前type类型(拓展点的)的所有实现的class,先不创建实例,懒加载方式 getExtensionClasses(); //cachedAdaptiveClass代表拓展点适配器class,也是缓存在ExtensionLoader对象中 if (cachedAdaptiveClass != null) { //如果存在,直接返回拓展点适配器class //cachedAdaptiveClass有可能在获取所有实现的时候能获取到,有可能获取不到 return cachedAdaptiveClass; } //如果不存在,直接创建拓展点适配器class,使用动态字节码生成 return cachedAdaptiveClass = createAdaptiveExtensionClass(); } // 加载拓展点的所有实现,获取type指定类型命名的文件,解析缓存到ExtensionLoader中 private Map<String, Class<?>> loadExtensionClasses() { cacheDefaultExtensionName(); Map<String, Class<?>> extensionClasses = new HashMap<>(); //DUBBO_INTERNAL_DIRECTORY=>META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionFactory(Type) loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName()); loadDirectory(extensionClasses, DUBBO_INTERNAL_DIRECTORY, type.getName().replace("org.apache", "com.alibaba")); loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName()); loadDirectory(extensionClasses, DUBBO_DIRECTORY, type.getName().replace("org.apache", "com.alibaba")); loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName()); loadDirectory(extensionClasses, SERVICES_DIRECTORY, type.getName().replace("org.apache", "com.alibaba")); return extensionClasses; } META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionFactory //看到配置,很明显ExtensionFactory这个拓展点接口有三个实现 //拓展点适配器实现:AdaptiveExtensionFactory //拓展点普通实现:SpiExtensionFactory,SpringExtensionFactory adaptive=org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory spi=org.apache.dubbo.common.extension.factory.SpiExtensionFactory spring=org.apache.dubbo.config.spring.extension.SpringExtensionFactory //根据以拓展点全路径名称查找相应文件,加载到拓展点的全部实现配置,配置如上 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 { String name = null; int i = line.indexOf('='); if (i > 0) { name = line.substring(0, i).trim(); line = line.substring(i + 1).trim(); } //获取一行配置,根据=号分割 //比如name=adaptive //line=org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory if (line.length() > 0) { 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); } } //进行拓展点实现的class,并且缓存到ExtensionLoader相应的属性中 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."); } //如果这个实现有@Adaptive,那么这个就是拓展点适配器实现,是一个特殊的拓展点实现 if (clazz.isAnnotationPresent(Adaptive.class)) { //赋值给ExtensionLoader的cachedAdaptiveClass属性 cacheAdaptiveClass(clazz); } else if (isWrapperClass(clazz)) { cacheWrapperClass(clazz); } else { //这个是真正提供拓展点功能的普通实现,将相应的class全部加载 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); //真正使用到的实现缓存起来,存在ExtensionLoader的cachedClasses属性 saveInExtensionClass(extensionClasses, clazz, name); } } } }
功能:使用上面创建的ExtensionLoader对象,根据name创建相应需要的拓展点实现 public T getExtension(String name) { if (StringUtils.isEmpty(name)) { throw new IllegalArgumentException("Extension name == null"); } if ("true".equals(name)) { return getDefaultExtension(); } //从缓存(cachedInstances)中获取当前拓展点的需要的实现,根据name参数 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; } //创建需要的拓展点实现(ExtensionLoader只是加载了class对象,并没有创建实例) 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); } //因为这些拓展实现是在容器启动后创建的,spring容器已经初始化完成,需要手动实现依赖注入 injectExtension(instance); Set<Class<?>> wrapperClasses = cachedWrapperClasses; if (CollectionUtils.isNotEmpty(wrapperClasses)) { for (Class<?> wrapperClass : wrapperClasses) { instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)); } } return instance; } catch (Throwable t) { throw new IllegalStateException("Extension instance (name: " + name + ", class: " + type + ") couldn't be instantiated: " + t.getMessage(), t); } }
-
总结
dubbo的SPI机制其实也很简单,就是把实现以key/value的形式都提前放在对应的文件中,然后需要的时候去获取对应的实现
1.getExtensionLoader方法核心功能就是创建ExtensionLoader对象,一个type对应一个ExtensionLoader,加载type类型的所有实现的class对象缓存在ExtensionLoader
2.getExtension方法核心功能就是根据当前的ExtensionLoader对象,获取名称为name的拓展点实现实例返回,并且缓存起来。
3.拓展点适配器是一个特殊的拓展点实现,这个有时候用来做选择拓展实现的策略的,起到一个适配器的作用,是一个特殊的拓展点实现,不一定需要。
4.任何扩展点触发SPI,都会先创建ExtensionFactory的ExtensionLoader,出于简单考虑,读者最好先去获取
ExtensionFactory这个扩展点进行试验,非ExtensionFactory的拓展点其实是getExtension才去真正加载拓展点的所有实现,先默认递归获取ExtensionFactory的拓展实现
(一)dubbo源码分析之SPI机制
猜你喜欢
转载自blog.csdn.net/weixin_38312719/article/details/105929243
今日推荐
周排行