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.Cat
cat cry...
以上及时基于Java SPI机制查找服务的实现。
2. Dubbo基于SPI思想实现
Dubbo对Java SPI发现机制加强而来。
- Java SPI标准的SPI会一次性实例化扩展点的所有实现,如果扩展实现很耗时,但如果没有用到也加载,会资源;还有如果实现类缺失依赖,实例化直接出错;
- 如果扩展点记载失败,连扩展点的名称都拿不到;
- 增加了IOC的支持,一个扩展点可以直接setter注入其他扩展点;
优先关注dubbo-common
子项目的com.alibaba.dubbo.common.extension
类包。
2.1. SPI接口定义
Dubbo定义了注解@SPI用于扩展,只要在接口上打了@SPI注解的接口才会去找找扩展点实现。
配置信息会从以下几个位置读取扩展信息:
- META-INF/dubbo/internal/
- META-INF/dubbo/
- 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);
}
}
// 获取代理对象class
private 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.AdaptiveCompiler
,com.alibaba.dubbo.common.compiler.support.JdkCompiler
,com.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
两个地方调用:
createExtension(String name)
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
处理逻辑:
@Adaptive
public 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;
}
}