API/SPI
JAVA程序开发中经常说到API和SPI,它们之间究竟有什么区别呢?
API
Application Programming Interface, 一些编程库暴露给开发者调用的接口就是API。一般需要调用者/客户端显式来调用。
SPI
Service Provider Interface, 一般用在框架开发中。正常情况下开发者/客户端不需要关心。主要是方便框架或者系统的扩展性,比如通过实现不同的策略类,自定义类并通过配置文件等方式,动态加载这部分SPI类。如果是Java核心库比如JDBC Driver的SPI接口一般通过Java线程上下文加载器来加载。另外SPI实现类都是框架或者库用来回调的。
SPI实现
java.util.ServiceLoader方式加载SPI实现类
- 建立目录META-INF/services
- 以SPI接口全路径名为文件名,文件内容是SPI具体实现类
- 打jar包
- 测试项目引入jar
- 测试代码调用SPI实现类
//将服务声明的文件名称定义为: example.spi.service.IService,与接口名称一致,其中的内容包括:
//example.spi.service.PrintServiceImpl
//example.spi.service.EchoServiceImpl
public static void main(String[] args) {
//实例化具体类时需要注意对应类有无参构造函数
ServiceLoader<Service> serviceLoader = ServiceLoader.load(IService.class);
for (IService service : serviceLoader) {
service.printInfo();
}
}
spring factory loader
SpringFactoriesLoader 读取文件 /META-INF/spring.factories
List<Foo> foos = SpringFactoriesLoader.loadFactories(Foo.class, null);
spring.factorie文件中key/value内容没有要求是接口名/实现。比如spring boot自动化配置中的key是org.springframework.boot.autoconfigure.EnableAutoConfiguration 而 values 是 @Configuration注解类
Dubbo ExtensionLoader
Dubbo ExtensionLoader 对比 ServiceLoader 做了一些增强
dubbo约定扩展点配置文件放在classpath下的/META-INF/dubbo,/META-INF/dubbo/internal,/META-INF/services目录下,配置文件名为接口的全限定名,配置文件内容为配置名=扩展实现类的全限定名。
- 根据key加载实现类,不像ServiceLoader获取接口所有的实现类
- 增加了对扩展点IoC和AOP的支持,一个扩展点可以直接setter注入其它扩展点