SpringBoot项目仅引入对应依赖时生效的工具类功能如何实现?
实现结论
可以实现,核心采用「API模块+空默认实现+SPI服务发现」的方案即可完全匹配你要求的使用方式,不需要依赖Spring容器,也不需要改动业务侧代码。
具体实现步骤
1. 拆分模块
拆为两个独立jar包:
- API包:所有业务项目必须引入的基础依赖,只定义对外工具类、SPI接口、空默认实现,未引入实现包时默认走空逻辑无任何操作
- 实现包:可选依赖,依赖API包实现真实业务逻辑,业务项目引入后自动生效
2. API包代码实现
首先定义SPI服务接口:
public interface DoSomethingHandler { void send(String apiUrl, String system, String content); }
编写对外暴露的工具类,内部用SPI加载实现类:
import java.util.ServiceLoader; public class DoSomethingUtil { private static final DoSomethingHandler ACTUAL_HANDLER; static { // SPI加载所有实现类 ServiceLoader<DoSomethingHandler> loader = ServiceLoader.load(DoSomethingHandler.class); DoSomethingHandler realImpl = null; for (DoSomethingHandler handler : loader) { realImpl = handler; break; } // 找不到实现就用空实现 ACTUAL_HANDLER = realImpl != null ? realImpl : (url, sys, content) -> {}; } public void send(String apiUrl, String system, String content) { ACTUAL_HANDLER.send(apiUrl, system, content); } }
3. 实现包代码实现
首先依赖API包,编写真实逻辑的实现类:
public class RealDoSomethingHandler implements DoSomethingHandler { @Override public void send(String apiUrl, String system, String content) { // 此处写你真实的业务逻辑,比如HTTP请求、日志上报等 System.out.printf("发送请求:地址=%s,来源系统=%s,内容=%s%n", apiUrl, system, content); } }
SPI配置:在实现包的resources/META-INF/services目录下新建文件,文件名为SPI接口的全类名(比如com.xxx.DoSomethingHandler),文件内容写实现类的全类名:
com.xxx.RealDoSomethingHandler
使用效果
- 业务项目只引入API包时:
new DoSomethingUtil().send(...)执行空逻辑,无任何操作 - 业务项目额外引入实现包后:不需要修改任何业务代码,同一行
send代码自动执行真实逻辑
SpringBoot适配优化(可选)
如果需要支持Spring注入配置、Bean管理,可以在实现包中新增自动配置类,工具类中优先从Spring上下文获取Bean,找不到再走SPI加载即可,不影响原有工具类的使用方式。
内容的提问来源于stack exchange,提问作者doraemon75
相关产品推荐
相关产品推荐

