什么是SPI机制
SPI全称service provider interface,是jdk内置的一种服务提供发现机制,是java提供的一套用来被第三方实现或者扩展的api,java spi四个主要概念
- service - 服务:服务是一组接口类,用来定义某些功能或特性,暴露给其它程序调用
- service provider interface - 服务提供者接口:定义接口,用来被别人去实现
- service provider - 服务提供者:接口的实现
ServiceLoader - 这个类是spi的核心,用赖加载的方式发现和加载服务的实现,它通过classpath的定位服务来实现,并将它们加载到JVM中。
Demo
编写接口与实现类
public interface UserService {
String queryUser();
}
public class CustomerImpl implements UserService {
@Override
public String queryUser() {
System.out.println("=====我是用户实现======");
return null;
}
}
public class MerchantImpl implements UserService {
@Override
public String queryUser() {
System.out.println("=====我是商户实现======");
return null;
}
}
接着在 classpath (及resource)下创建文件夹 META-INF/services,并在文件夹下创建一个文件,名称为:com.plat.paygate.order.spi.UserService(接口的全路径名)
在文件中写上接口的实现类
com.plat.paygate.order.spi.MerchantImpl
com.plat.paygate.order.spi.CustomerImpl
测试 ``` public void test() { ServiceLoader
serviceLoader = ServiceLoader.load(UserService.class); Iterator iterator = serviceLoader.iterator(); while (iterator.hasNext()){ UserService userService = iterator.next();
userService.queryUser();
} }
//输出 =====我是商户实现====== =====我是用户实现====== ```
总结
优点
java是面向接口编程,这样可以让接口与实现类解耦,使得接口与具体业务分离,接口只需要定义标准即可,具体实现由其接入的框架去实现,如java.sql.Driver,定义了响应接口,mysql和oracle可以根据自己的需求各自实现自己的实现类
缺点
- 不能按需加载。虽然 ServiceLoader 做了延迟载入,但是基本只能通过遍历全部获取,也就是接口的实现类得全部载入并实例化一遍。如果你并不想用某些实现类,或者某些类实例化很耗时,它也被载入并实例化了,这就造成了浪费。
- 获取某个实现类的方式不够灵活,只能通过 Iterator 形式获取,不能根据某个参数来获取对应的实现类。
- 多个并发多线程使用 ServiceLoader 类的实例是不安全的。
- 加载不到实现类时抛出并不是真正原因的异常,错误很难定位。