一、JDK SPI机制
什么是SPI
- SPI(全称Service Provider Interface),Java提供的一套用来被第三方实现或者扩展的接口,可以用来启用框架扩展和替换组件。 SPI的作用就是为这些被扩展的API寻找服务实现。
- SPI是服务消费方制定的接口规范(例如JDK制定JDBC规范,各个数据库厂商具体实现,在实际使用中[例如:mybatis框架使用JDK接口进行连接数据库操作])。
- API (Application Programming Interface)是提供方制定接口并完成对接口的实现,消费方仅仅依赖接口调用,且无权选择不同实现 。
public interface UserService {
/**
* 用户注册接口
*
* @param phone 注册手机号
* @return
*/
String register(String phone);
}
public class JDUserServiceImpl implements UserService {
@Override
public String register(String phone) {
return "京东用户,注册手机号:"+phone;
}
}
public class ALiUserServiceImpl implements UserService {
@Override
public String register(String phone) {
return "阿里巴巴注册用户,注册手机号:"+phone;
}
public class SPIDemo {
public static void main(String[] args) {
ServiceLoader<UserService> serviceLoaders = ServiceLoader.load(UserService.class);
serviceLoaders.forEach(server -> {
//System.out.println("调用服务");
System.out.println(server.register("110"));
});
}
}
输出:
阿里巴巴注册用户,注册手机号:110
京东用户,注册手机号:110
SPI应用
mybatis、shardingSphere框架都用到了JDK的SPI技术。mybatis在连接不同数据库实现中,读取驱动包下META-INF/services/java.sql.Driver文件(java.sql.Driver为接口名)中配置的连接数据库的实现(Driver实现类)
Java中SPI局限
只能遍历所有的实现,并全部实例化。
配置文件中只是简单的列出了所有的扩展实现,无法对扩展实现命名。导致在程序中很难去准确的引用它们。
扩展如果依赖其他的扩展,做不到自动注入和装配。
扩展很难和其他的框架集成,比如扩展里面依赖了一个Spring bean,原生的Java SPI不支持。
二、SPI优势
不需要改动源码就可以实现扩展,解耦。
实现扩展对原来的代码几乎没有侵入性。
只需要添加配置就可以实现扩展,符合开闭原则。