Java SPI 配置文件必须置于 src/main/resources/META-INF/services/ 下,文件名为接口全限定名(大小写敏感、无后缀),内容为每行一个 UTF-8 无 BOM 编码的实现类全限定名;模块化项目还需在 module-info.java 中声明 uses 和 requires。

Java 中 SPI 配置文件必须放在 classpath 根路径下的 META-INF/services/ 目录里,不能放错位置,否则 ServiceLoader 完全找不到它。
配置路径必须是 src/main/resources/META-INF/services/
在 Maven 或 Gradle 项目中,要把配置文件放在 src/main/resources/META-INF/services/ 下。这个目录会被构建工具自动复制到编译输出目录(如 target/classes/ 或 build/classes/java/main/)的根路径下,确保运行时 classpath 能直接访问到 META-INF/services/。
- 别放在
src/main/java/META-INF/services/—— Java 源码目录不会被当作资源路径处理,文件不会进入 classpath - 别手动建在
target/classes/里 —— 下次 clean 编译就没了,不持久 - IDE 里如果看不到该路径,可右键
resources→ New → Directory,逐级创建META-INF/services
文件名必须是接口的全限定名
假设服务接口是 com.example.PaymentService,那就在 META-INF/services/ 下新建一个纯文本文件,名字就是:
- 大小写严格匹配,
Com.Example.Paymentservice或com/example/PaymentService都无效 - 不能加后缀(如 .txt),也不能有空格或非法字符
- 没有文件内容时,
ServiceLoader仍会识别该接口,但不会加载任何实现
文件内容和编码要求
文件内每行写一个实现类的全限定名,例如:
立即学习“Java免费学习笔记(深入)”;
com.example.alipay.AlipayPayment com.example.wechat.WechatPayment
- 每行一个类,不能有空行、注释或多余空格
- 必须用 UTF-8 无 BOM 编码 —— Windows 记事本默认可能带 BOM,建议用 VS Code、IntelliJ 或 Notepad++ 保存为 “UTF-8”(不是“UTF-8 with BOM”)
- 实现类必须有 public 无参构造方法,否则实例化失败且
ServiceLoader默认静默跳过(需手动 try-catch 才能捕获异常)
模块化项目(Java 9+ module-info.java)要额外声明
如果用了模块系统,仅放配置文件还不够,还必须在 module-info.java 中声明:
-
uses com.example.PaymentService;—— 表示当前模块使用该服务接口 -
requires xxx.module.name;—— 确保包含实现类的模块被依赖并可访问
否则即使配置文件存在,ServiceLoader 也查不到实现类。


















