一、JDK SPI机制

什么是SPI

  1. SPI(全称Service Provider Interface),Java提供的一套用来被第三方实现或者扩展的接口,可以用来启用框架扩展和替换组件。 SPI的作用就是为这些被扩展的API寻找服务实现。
  2. SPI是服务消费方制定的接口规范(例如JDK制定JDBC规范,各个数据库厂商具体实现,在实际使用中[例如:mybatis框架使用JDK接口进行连接数据库操作])。
  3. API (Application Programming Interface)是提供方制定接口并完成对接口的实现,消费方仅仅依赖接口调用,且无权选择不同实现 。

image.pngimage.png

  1. public interface UserService {
  2. /**
  3. * 用户注册接口
  4. *
  5. * @param phone 注册手机号
  6. * @return
  7. */
  8. String register(String phone);
  9. }
  10. public class JDUserServiceImpl implements UserService {
  11. @Override
  12. public String register(String phone) {
  13. return "京东用户,注册手机号:"+phone;
  14. }
  15. }
  16. public class ALiUserServiceImpl implements UserService {
  17. @Override
  18. public String register(String phone) {
  19. return "阿里巴巴注册用户,注册手机号:"+phone;
  20. }
  21. public class SPIDemo {
  22. public static void main(String[] args) {
  23. ServiceLoader<UserService> serviceLoaders = ServiceLoader.load(UserService.class);
  24. serviceLoaders.forEach(server -> {
  25. //System.out.println("调用服务");
  26. System.out.println(server.register("110"));
  27. });
  28. }
  29. }
  30. 输出:
  31. 阿里巴巴注册用户,注册手机号:110
  32. 京东用户,注册手机号:110

SPI应用

mybatis、shardingSphere框架都用到了JDK的SPI技术。mybatis在连接不同数据库实现中,读取驱动包下META-INF/services/java.sql.Driver文件(java.sql.Driver为接口名)中配置的连接数据库的实现(Driver实现类)

Java中SPI局限

只能遍历所有的实现,并全部实例化。
配置文件中只是简单的列出了所有的扩展实现,无法对扩展实现命名。导致在程序中很难去准确的引用它们。
扩展如果依赖其他的扩展,做不到自动注入和装配。
扩展很难和其他的框架集成,比如扩展里面依赖了一个Spring bean,原生的Java SPI不支持。

二、SPI优势

不需要改动源码就可以实现扩展,解耦。
实现扩展对原来的代码几乎没有侵入性。
只需要添加配置就可以实现扩展,符合开闭原则。