Java 服务提供者接口
- 什么是java Spi
- SPI组件构成
- API和SPI区别
- SPI实战演练
什么是java Spi
SPI: 用于发现和加载与给定接口匹配的实现。服务提供者接口:(供服务的提供者或者框架扩展者去实现服务的一套接口标准)
SPI组件构成
ServiceLoader
SPI 的核心是 ServiceLoader 类。加载服务实现的类。具有延迟发现和加载实现的作用。
它使用上下文类路径来定位提供者实现并将它们放入内部缓存中即
通过读取服务提供者配置的META-INF/services下的文件信息获取对应服务提供者接口的实现类。
Service(服务)
一组众所周知的编程接口和类,存在零个、一个或多个服务提供者。它们提供对某些特定应用程序功能或特性的访问。
Service Provider Interface(服务提供者接口)
为了实现特定应用功能的接入,制定的一套标准化的接口,被用于服务提供者去实现该接口,完成对功能的实现。
一般为具体的sdk服务厂家提供的接口标准。(jdk 为 oracle 驱动提供的接口)
Service Provider (服务提供者(实现这个服务的具体模块或者类))
实现提供者接口的具体实现。通过配置 META-INF/services下的文件来确定服务器提供者接口和服务提供者实现。
API和SPI区别
- 当实现方提供了接口和实现,我们可以通过调用实现方的接口从而拥有实现方给我们提供的能力,这就是 API ,这种接口和实现都是放在实现方的。
- 当接口存在于调用方这边时,就是 SPI ,由接口调用方确定接口规则,然后由不同的厂商去根据这个规则对这个接口进行实现,从而提供服务。
Java 生态系统中的 SPI 示例
SPI实战演练
- 这里我们通过日志类型进行项目演示
- 我们首先创建一个名为service-provider-interface的 Maven 项目
- 然后我们创建一个Logger接口用于日志输出
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
package com.ahut.spi;
/**
* 日志接口定义相关日志信息输出
* @author Cherubr
* 通用服务用于日志输出
*/
public interface Logger {
/**
* 输出日志
* @param message
*/
void write(String message);
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
package com.ahut.spi;
/**
* @author Sumin.G
* @title: Logger
* @projectName java-base
* @description: SPI 接口提供者 用于服务提供者去实现该接口,完成对功能的实现
* @date 2022/9/69:40
*/
public interface LoggerProvider {
/**
* 创建日志管理类
* @return
*/
Logger create();
}
|
- 最后是我们的serviceloader类加载对应接口
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
26
27
28
29
30
31
32
33
34
35
36
37
|
package com.ahut.spi.impl;
import com.ahut.spi.LoggerProvider;
import java.util.ArrayList;
import java.util.List;
import java.util.ServiceLoader;
/**
* @author Sumin.G
* @title: Logger
* @projectName java-base
* @description: TODO
* @date 2022/9/69:40
*/
public class LoggerManager {
private static final LoggerManager SERVICE = new LoggerManager();
public static List<LoggerProvider> loggerList;
private LoggerManager() {
ServiceLoader<LoggerProvider> loader = ServiceLoader.load(LoggerProvider.class);
List<LoggerProvider> list = new ArrayList<>();
for (LoggerProvider log : loader) {
list.add(log);
}
loggerList = list;
}
public static LoggerManager getService() {
return SERVICE;
}
}
|
到这里用户的服务提供者完成。
- 下面我们创建服务提供者实现
创建一个名为service-provider的 Maven 项目,并将 service-provider-interface 依赖项添加到pom.xml
创建SPI实现类
用于构建对应Logger 日志具体实现类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
package com.ahut.spi.server;
import com.ahut.spi.Logger;
import com.ahut.spi.LoggerProvider;
/**
* @author Sumin.G
* @title: LogbackProvider
* @projectName java-base
* @description: TODO
* @date 2022/9/617:16
*/
public class LogbackProvider implements LoggerProvider {
@Override
public Logger create() {
return new Logback();
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
package com.ahut.spi.server;
import com.ahut.spi.Logger;
/**
* @author Sumin.G
* @title: Logback
* @projectName java-base
* @description: TODO
* @date 2022/9/610:16
*/
public class Logback implements Logger {
@Override
public void write(String message) {
System.out.println("logback输出日志 "+message);
}
}
|
为了被发现,我们创建了一个提供者配置文件
META-INF/services/com.ahut.spi.LoggerProvider –>文件内容为实现类名称 com.ahut.spi.server.LogbackProvider
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
package com.ahut;
import com.ahut.spi.impl.LoggerManager;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
testSpi();
}
public static void testSpi(){
LoggerManager.loggerList.stream().forEach(e->{
e.create().write("123");
});
}
}
|