ServiceLoader 是 Java 提供的一种服务发现机制,用于实现服务提供者接口(SPI)的动态加载。它可以在运行时发现并加载实现了某个接口的服务提供者,实现解耦和动态扩展功能。

工作原理

  1. 接口定义

    • 你需要为某个功能定义一个接口(或抽象类),供其他模块实现。
  2. 服务提供者实现

    • 其他模块可以实现这个接口,提供不同的实现。
  3. 配置文件

    • 在实现模块的资源目录下创建文件:META-INF/services/<接口的全限定名>
    • 文件内容是实现类的全限定名,每行一个。
  4. 使用 ServiceLoader

    • 使用 ServiceLoader.load(Interface.class) 来加载接口的所有实现。
    • ServiceLoader 会在类路径中查找 META-INF/services 目录,读取配置文件,实例化实现类。

示例代码

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
// 定义接口
public interface MyService {
void execute();
}

// 实现类1
public class MyServiceImpl1 implements MyService {
public void execute() {
System.out.println("Implementation 1");
}
}

// 实现类2
public class MyServiceImpl2 implements MyService {
public void execute() {
System.out.println("Implementation 2");
}
}

// 使用ServiceLoader
public class ServiceLoaderExample {
public static void main(String[] args) {
ServiceLoader<MyService> loader = ServiceLoader.load(MyService.class);
for (MyService service : loader) {
service.execute();
}
}
}

优点

  • 解耦:客户端无需知道具体实现类。
  • 动态扩展:可以在不修改客户端代码的情况下添加新实现。
  • 模块化:适用于插件式架构。

注意事项

  • 配置文件路径和内容必须正确。
  • 所有实现类必须有无参构造函数。
  • ServiceLoader 使用时是懒加载,第一次使用时才会初始化实现类。