首页
SPI(Service Provider Interface)
Java
步骤
- 定义接口【SPI】;
- 创建接口的实现类【ASPI】【BSPI】;
- 在【META-INF/services/】目录下创建接口全限定名命名的文件【jdk.spi.SPI】;
- 文件内容为实现类的全限定名;
com.aa.ASPI com.bb.BSPI
- 使用ServiceLoader加载所有的文件内定义的实现类。
ServiceLoader<SPI> spis = ServiceLoader.load(SPI.class); // 返回代理对象,懒加载方式。
public final class ServiceLoader<S> implements Iterable<S>
Spring
步骤
- 定义接口和实现类;
- 只读取【META-INF/spring.factories】文件;
jdk.spi.SPI=com.aa.ASPI,com.bb.BSPI
- 使用SpringFactoriesLoader加载实现类(非懒加载)。
List<SPI> spis= SpringFactoriesLoader.loadFactories(SPI.class, Thread.currentThread().getContextClassLoader());
SpringFactoriesLoader
Dubbo
步骤
- 定义接口,需要使用dubbo的注解@SPI修饰;
- 支持三个拓展点:【META-INF/dubbo/internal】内部拓展点;【META-INF/dubbo】自定义拓展点;【META-INF/services】兼容java;
- 同样使用接口全限定名命名的文件,文件内容为键值对方式;
a=com.aa.ASPI b=com.bb.BSPI
- 使用ExtensionLoader加载文件内定义的实现类,通过键获取。
ExtensionLoader<SPI> spis = ExtensionLoader.getExtensionLoader(SPI.class); SPI a = spis.getExtension("a"); SPI b = spis.getExtension("b");
@Adaptive
自适应扩展实现类,可以修饰类(接口,枚举)和方法,优先级高于@SPI,使用时要求方法入参必须包含org.apache.dubbo.common.URL。
@SPI("impl1")
public interface SimpleExt {
@Adaptive({"key1", "key2"})
String yell(URL url, String s);
}
先判断URL种的key1参数,不存在则判断key2,均不存在则使用impl1对应的默认实现。
@Activate
自动激活扩展类,优先级最高,使用在实现类上,包含group、value、before、after、order五个参数。