module-info.java 不影响服务加载优先级或运行时对象筛选,仅在编译期声明依赖与导出;ServiceLoader 按模块路径(声明顺序)、类路径顺序查找实现,筛选需在代码中通过流操作、注解或框架机制实现。

module-info.java 本身不控制服务加载器的“优先级”,也不参与运行时变量对象的筛选。它只在编译期和模块解析阶段声明静态依赖与导出规则,服务加载行为由 ServiceLoader 在运行时按类路径或模块路径顺序扫描实现类,不读取 module-info 中的数值或权重。
服务加载的实际机制
ServiceLoader 按照以下顺序查找服务实现:
- 先扫描 模块路径(--module-path)中已解析的模块,按模块声明顺序(即 JVM 加载模块的顺序)遍历;
- 再扫描 类路径(-cp)中的 META-INF/services/xxx 文件;
- 同一模块内多个实现类按 文件系统目录遍历顺序 返回,无稳定排序保证;
- module-info.java 中的
provides ... with仅用于编译期验证和模块图构建,不改变 ServiceLoader 的实例化顺序。
如何影响服务加载结果(非“优先级”)
若需让某实现更早被选中或过滤特定实例,需在代码中干预,而非靠 module-info:
- 用
ServiceLoader.load(...).stream().findFirst()主动取第一个(但顺序不可靠); - 在服务接口中定义
int priority()方法,由使用者手动排序; - 通过配置(如 SPI 配置文件加权重字段)+ 自定义加载器解析;
- 避免多模块提供同一服务接口,改用明确命名的模块导出不同子接口。
变量对象筛选与 module-info 无关
运行时对变量对象(如 List
- 用 Stream.filter() 按属性、类型或注解条件过滤;
- 结合 ServiceLoader + 自定义注解(如 @Preferred)做标记,再反射判断;
- 使用 Spring 等框架的 @Qualifier 或 @Primary 实现语义化选择。
module-info.java 不具备运行时能力,不能参与对象创建、筛选或排序。它只是模块系统的“身份证”和“契约说明书”。真正要控制加载行为或筛选结果,得在代码逻辑或容器机制里下功夫。

















