Dubbo-SPI

来源:互联网 发布:沙巴克传奇有哪些端口 编辑:程序博客网 时间:2024/05/17 07:56

SPI

1. 定义

SPI即Service Provider Interface,服务提供接口。

​ 系统中抽象的各个模块,往往有很多不同的实现方案,比如日志模块,xml解析模块,jdbc模块的方案等。面向对象的设计里,我们一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里设计具体的实现类,就违反了可插拔的原则,如果需要替换一种实现,就需要修改代码。

​ 为了实现在模块装配的时候能不在程序里动态指明,就需要一种服务发现机制。JAVA SPI就是提供这样的一个机制:为某个接口寻找服务实现的机制。有点类似IOC的思想,就是将转配的控制权一到程序之外,在模块化设计中这个机制尤其重要。

1.1. Java SPI的约定

​ 当服务的提供者,提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同事创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过jar包META-INF/services里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。

​ 基于这样一个约定就能很好的找到接口的实现类,而不需要在代码里定制。jdk提供服务实现查找的一个工具类:java.util.ServiceLoader

1.2. 范例

1.3. Demo

定义接口类

package cn.test.spi;public interface Animal {  String cry();}

接口实现类

package cn.test.spi;public class Cat implements Animal {    public String cry() {        return "cat cry...";    }}public class Dog implements Animal {    public String cry() {        return "dog cry...";    }}

运行

package cn.test.spi;import java.util.Iterator;import java.util.ServiceLoader;public class TestAnimal {    public static void main(String[] args) {        ServiceLoader<Animal> loader = ServiceLoader.load(Animal.class);        Iterator<Animal> iterator = loader.iterator();        while (iterator.hasNext()) {            Animal animal = iterator.next();            System.out.println(animal.getClass());            System.out.println(animal.cry());        }    }}

其中,在META-INF/services目录中创建文件cn.test.spi.Animal,内容为cn.test.spi.Cat

输出结果为:

class cn.test.spi.Catcat cry...

以上及时基于Java SPI机制查找服务的实现。

2. Dubbo基于SPI思想实现

Dubbo对Java SPI发现机制加强而来。

  1. Java SPI标准的SPI会一次性实例化扩展点的所有实现,如果扩展实现很耗时,但如果没有用到也加载,会资源;还有如果实现类缺失依赖,实例化直接出错;
  2. 如果扩展点记载失败,连扩展点的名称都拿不到;
  3. 增加了IOC的支持,一个扩展点可以直接setter注入其他扩展点;

优先关注dubbo-common子项目的com.alibaba.dubbo.common.extension类包。

2.1. SPI接口定义

Dubbo定义了注解@SPI用于扩展,只要在接口上打了@SPI注解的接口才会去找找扩展点实现。

配置信息会从以下几个位置读取扩展信息:

  1. META-INF/dubbo/internal/
  2. META-INF/dubbo/
  3. META-INF/services/

com.alibaba.dubbo.rpc.ProxyFactory为例:

@SPI("javassist")public interface ProxyFactory {    @Adaptive({Constants.PROXY_KEY})    <T> T getProxy(Invoker<T> invoker) throws RpcException;    @Adaptive({Constants.PROXY_KEY})    <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException;}

2.2. ExtensionLoader类解析

每个定义SPI的接口都会构建一个ExtensionLoader实例,存储在ExtensionLoader.EXTENSION_LOADERS属性中。

// 触发入口public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {    // check      ...   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;}// 构建ExtensionLoader对象private ExtensionLoader(Class<?> type) {  this.type = type;  // 当type不是ExtensionFactory类型时,寻找ExtensionFactory对象,  // 赋值给ExtensionLoader的objectFactory,为了之后IOC寻找依赖对象时使用;  // 由此可以看出,如果使用dubbo的SPI,第一个初始化的就是ExtensionFactory扩展节点;  // 下节通过动态扩展ExtensionFactory节点来了解代码运行轨迹;  objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());}

2.3. 加载流程

提供由SPI扩展对象依赖属性的查找入口。

// 当clazz不是ExtensionFactory.clss,第一个调用触发ExtensionLoader<ExtensionFactory>对象初始化;ExtensionLoader.getExtensionLoader(clazz);private ExtensionLoader(Class<?> type) {  this.type = type;  // getAdaptiveExtension方法触发初始化;  // 通过该方法获得指定类型的代理对象,并非实际的业务处理对象;  // PS:代理对象生成:1、自建[通过@Adaptive标识];2、动态代理  objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());}// 创建动力扩展对象private T createAdaptiveExtension() {  try {    // 1. getAdaptiveExtensionClass() 获取代理对象class    // 2. 对指定代理class实例化    // 3. 代理对象如有依赖,可从SPI上下文找到,通过setter方式植入    return injectExtension((T) getAdaptiveExtensionClass().newInstance());  } catch (Exception e) {    throw new IllegalStateException("Can not create adaptive extenstion " + type + ", cause: " + e.getMessage(), e);  }}// 获取代理对象classprivate Class<?> getAdaptiveExtensionClass() {  // 通过配置文件获取扩展点 实现类  getExtensionClasses();  // 初始化时,如果有指定代理对象class,直接返回  if (cachedAdaptiveClass != null) {    return cachedAdaptiveClass;  }  // 初始化时,如果并没有指定代理对象class,运行时通过字节码方式动态生成class  return cachedAdaptiveClass = createAdaptiveExtensionClass();}// 加载扩展实现类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;}// 加载扩展实现类private Map<String, Class<?>> loadExtensionClasses() {  final SPI defaultAnnotation = type.getAnnotation(SPI.class);  if (defaultAnnotation != null) {    String value = defaultAnnotation.value();    if (value != null && (value = value.trim()).length() > 0) {      String[] names = NAME_SEPARATOR.split(value);      if (names.length > 1) {        throw new IllegalStateException("more than 1 default extension name on extension " + type.getName()                                        + ": " + Arrays.toString(names));      }      if (names.length == 1) cachedDefaultName = names[0];    }  }  Map<String, Class<?>> extensionClasses = new HashMap<String, Class<?>>();  // 加载文件 META-INF/dubbo/internal/{type.getName()}  loadFile(extensionClasses, DUBBO_INTERNAL_DIRECTORY);  // 加载文件 META-INF/dubbo/{type.getName()}  loadFile(extensionClasses, DUBBO_DIRECTORY);  // 加载文件 META-INF/services/{type.getName()}  loadFile(extensionClasses, SERVICES_DIRECTORY);  return extensionClasses;}// 在初始后,并没有找到指定的代理class,则动态生成;private Class<?> createAdaptiveExtensionClass() {  // 生成class的string值  String code = createAdaptiveExtensionClassCode();  ClassLoader classLoader = findClassLoader();  // 获取Compiler对象  com.alibaba.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(com.alibaba.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();  // 将生成的code,以及compiler,加载  return compiler.compile(code, classLoader);}

从下面截图可以获悉:Compiler的扩展类有三个,分别为:com.alibaba.dubbo.common.compiler.support.AdaptiveCompilercom.alibaba.dubbo.common.compiler.support.JdkCompilercom.alibaba.dubbo.common.compiler.support.JavassistCompiler。其中代理类为:AdaptiveCompiler

实际执行轨迹为:由于属性name为空,会通过loader.getDefaultExtension(),获取默认的扩展实现类。

public T getDefaultExtension() {  getExtensionClasses();  // 获取默认的扩展实现的名字, 而默认扩展实现的名字有getExtensionClasses()方法执行获得;  if (null == cachedDefaultName || cachedDefaultName.length() == 0      || "true".equals(cachedDefaultName)) {    return null;  }  return getExtension(cachedDefaultName);}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;}// 此方法已经getExtensionClasses方法同步过。private Map<String, Class<?>> loadExtensionClasses() {  // 从SPI标签的value获取  final SPI defaultAnnotation = type.getAnnotation(SPI.class);  if (defaultAnnotation != null) {    String value = defaultAnnotation.value();    if (value != null && (value = value.trim()).length() > 0) {      String[] names = NAME_SEPARATOR.split(value);      if (names.length > 1) {        throw new IllegalStateException("more than 1 default extension name on extension " + type.getName()                                        + ": " + Arrays.toString(names));      }      if (names.length == 1) cachedDefaultName = names[0];    }  }... // 代码省略}// Compiler的接口代码如下:// 因此,Dubbo默认使用javasisist字节码类库@SPI("javassist")public interface Compiler {    Class<?> compile(String code, ClassLoader classLoader);}

2.4. IOC

动态注入属性值

injectExtension两个地方调用:

  1. createExtension(String name)
  2. createAdaptiveExtension()
private T injectExtension(T instance) {  try {    // objectFacatory 为ExtensionFactory的代理对象;即:AdaptiveExtensionFactory    if (objectFactory != null) {      for (Method method : instance.getClass().getMethods()) {        // 通过set方法动态注入属性        if (method.getName().startsWith("set")            && method.getParameterTypes().length == 1            && Modifier.isPublic(method.getModifiers())) {          Class<?> pt = method.getParameterTypes()[0];          try {            String property = method.getName().length() > 3 ? method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4) : "";            // 通过objectFacatory的getExtension获取属性值;            Object object = objectFactory.getExtension(pt, property);            if (object != null) {              // set属性值              method.invoke(instance, object);            }          } catch (Exception e) {            logger.error("fail to inject via method " + method.getName()                         + " of interface " + type.getName() + ": " + e.getMessage(), e);          }        }      }    }  } catch (Exception e) {    logger.error(e.getMessage(), e);  }  return instance;}

下面看下AdaptiveExtensionFactory处理逻辑:

@Adaptivepublic class AdaptiveExtensionFactory implements ExtensionFactory {    private final List<ExtensionFactory> factories;    public AdaptiveExtensionFactory() {      //实例化AdaptiveExtensionFactory时候,会将所有的扩展点对象放入factories属性中;        ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);        List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();        for (String name : loader.getSupportedExtensions()) {            list.add(loader.getExtension(name));        }        factories = Collections.unmodifiableList(list);    }    // 查找执行上下文对象的时候,会按照放入factories对象的顺序;    // 以此从扩展点对象获取,直至找到位置;    public <T> T getExtension(Class<T> type, String name) {        for (ExtensionFactory factory : factories) {            T extension = factory.getExtension(type, name);            if (extension != null) {                return extension;            }        }        return null;    }}
原创粉丝点击