java的spi机制

SPI机制

Java SPI思想梳理
1.看了一些spi机制相关的文章,尝试写出自己的理解,不正确的地方欢迎指出。
java的spi机制,相对于api机制;

  • api机制:模块之间依赖接口而不依赖具体的实现,具体的实现类的修改不影响接口的使用。而调用方不需要关心接口的具体实现是什么,只需要知道自己需要什么能力即可。
  • spi机制:提供方制定了接口,并事先准备好多套实现;使用方来决定使用哪种实现。

2 SPI具体约定
java spi的具体约定为:当服务的提供者,提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。 基于这样一个约定就能很好的找到服务接口的实现类,而不需要再代码里制定。jdk提供服务实现查找的一个工具类:java.util.ServiceLoader

java.util.ServiceLoader使用
Java.util.ServiceLoader这个类来从配置文件中加载子类或者接口的实现类。以前从来没有使用过这个类,进去大概看了一下具体的实现。主要是从META-INF/services这个目录下的配置文件加载给定接口或者基类的实现,ServiceLoader会根据给定的类的full name来在META-INF/services下面找对应的文件,在这个文件中定义了所有这个类的子类或者接口的实现类,返回一个实例。

首先定义接口
public interface Search {

   public List<String> search(String keysord);
}

两个实现类
public class DocSearch implements Search {

   @Override
   public List<String> search(String keysord) {
       System.out.println("dearch in doc");
       return null;
   }
}

public class DbSearch implements Search {

   @Override
   public List<String> search(String keysord) {
       System.out.println("db search");
       return null;
   }
}

然后 在META-INF/services目录下新建文件:
spi.Search
文件内容为:实现类的全路径
#写上Search接口的实现类,这样就可以知道调用哪个实现类了
spi.DocSearch
spi.DbSearch

测试一下:
public class Test {
       public static void main(String[] args) {
           //加载到spi.Search文件下面配置的实现类
           ServiceLoader<Search> s = ServiceLoader.load(Search.class);
           Iterator<Search> iterator = s.iterator();
           while (iterator.hasNext()) {
               System.out.println("#");
               Search search =  iterator.next();
               search.search("hello world");
           }
       }
}

推荐阅读更多精彩内容