SPI 简介
SPI 全称为 Service Provider Interface,是JDK内置的一种服务提供发现机制。
作用
实现方式
- 标准制定者制定接口
- 在
META-INF/services/目录中创建以接口全限定名命名的文件,该文件内容为接口具体实现类的全限定名,文件编码必须为UTF-8。如果该Service有多个服务实现,则每一行写一个服务实现(#后面的内容为注释)。
- 如SPI的实现类为jar,则需要将其放在当前程序的classpath下。
- 接口的具体实现类必须有一个无参构造方法。
- 使用
ServiceLoader.load(Class clazz); 自动寻找接口的实现类。
基于这样一个方式就能很好的找到服务接口的实现类,而不需要再代码里制定。
jdk提供服务实现查找的一个工具类:java.util.ServiceLoader。
示例
项目结构:

定义一个接口:HelloService.java
1 2 3 4 5 6 7 8 9 10 11 12 13
| package com.lzumetal.javalean.spi.service;
public interface HelloService {
String sayHello(String name);
}
|
接口实现类
本示例中 HelloService 有两个实现类,分别为:EnglishDemoServiceImpl和ChineseDemoServiceImpl,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package com.lzumetal.javalean.spi.service.impl;
import com.lzumetal.javalean.spi.service.HelloService;
public class ChineseHelloServiceImpl implements HelloService {
@Override public String sayHello(String name) { return "你好," + name; }
}
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package com.lzumetal.javalean.spi.service.impl;
import com.lzumetal.javalean.spi.service.HelloService;
public class EnglishHelloServiceImpl implements HelloService{
@Override public String sayHello(String name) { return "hello," + name; }
}
|
在src/main/resources下创建META-INF/services/目录,并新建com.lzumetal.javalean.spi.service.HelloService 文件,内容如下:
1 2 3 4 5
| #English implementation com.lzumetal.javalean.spi.service.impl.EnglishHelloServiceImpl
#Chinese implementation com.lzumetal.javalean.spi.service.impl.ChineseHelloServiceImpl
|
测试类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| package com.lzumetal.javalean.spi.test;
import com.lzumetal.javalean.spi.service.HelloService;
import java.util.Iterator; import java.util.ServiceLoader;
public class SpiTest {
public static void main(String[] args) { ServiceLoader<HelloService> serviceLoader = ServiceLoader.load(HelloService.class); Iterator<HelloService> serviceIterator = serviceLoader.iterator(); while (serviceIterator != null && serviceIterator.hasNext()) { HelloService helloService = serviceIterator.next(); System.out.println("calss:" + helloService.getClass().getName() + "|sayHello method:" + helloService.sayHello("world")); } } }
|
运行结果
1 2
| calss:com.lzumetal.javalean.spi.service.impl.EnglishHelloServiceImpl|sayHello method:hello,world calss:com.lzumetal.javalean.spi.service.impl.ChineseHelloServiceImpl|sayHello method:你好,world
|