Java 9+模块系统通过provides...with...语句实现多算法库统一封装:定义Algorithm接口及子接口,各子模块在module-info.java中声明具体实现类,主模块用ServiceLoader动态加载并统一调度。

通过 provides with 实现多算法库的模块化统一封装,核心在于利用 Java 9+ 模块系统中的 服务加载机制(Service Provider Interface, SPI),而非语法上直接写 “provides with”——Java 模块声明中实际使用的是 provides … with … 这一完整语句,用于将具体实现类注册为某服务接口的提供者。
明确服务接口与实现分离
先定义一个统一的算法能力契约,比如:
- 创建接口
Algorithm<i o></i>,含apply(I input): O方法 - 再定义更具体的业务接口,如
ImageFilter、TextTokenizer、PathFinder,均继承或适配Algorithm - 所有算法实现类(如
BlurFilterImpl、BertTokenizerImpl、AStarPathfinder)不暴露具体类型,只实现对应接口
在 module-info.java 中声明服务提供
每个封装算法子模块(如 com.example.filters)需在其 module-info.java 中写:
module com.example.filters {
requires com.example.algorithm.api;
provides com.example.algorithm.api.ImageFilter
with com.example.filters.BlurFilterImpl,
com.example.filters.SharpenFilterImpl;
}
同理,NLP 模块写:
module com.example.nlp {
requires com.example.algorithm.api;
provides com.example.algorithm.api.TextTokenizer
with com.example.nlp.BertTokenizerImpl,
com.example.nlp.JiebaTokenizerImpl;
}
关键点:同一个接口可被多个模块提供;同一模块可提供多个接口;每个 with 后列出的类必须是该接口的具体实现类,且具有无参构造器或支持 ServiceLoader 默认实例化。
统一调用入口:基于标准变量接口获取实例
主模块或调度层只需依赖接口模块,用标准方式获取可用实现:
- 通过
ServiceLoader.load(ImageFilter.class)动态加载所有已注册的图像滤镜 - 可结合配置(如
application.properties中设filter.type=blur)选择特定实现 - 封装一个工厂类,隐藏加载逻辑,对外只暴露
AlgorithmFactory.getFilter(String type)等方法,返回统一类型变量 - 所有算法实例都视为
ImageFilter变量,调用时无需 instanceof 或强制转型
配套支撑:确保模块可见性与运行时可用
注意三项约束:
-
requires的接口模块必须导出(exports)其 API 包,否则其他模块无法编译通过 - 提供者模块不能
opens其实现包(除非需反射),但必须保证实现类是 public 且在模块路径下可访问 - 运行时需将所有 provider 模块加入模块路径(
--module-path),而非传统 classpath;否则ServiceLoader查不到实现

















