uses声明用于表明模块消费服务接口,须在module-info.java中声明,仅依赖接口模块而非实现模块,配合serviceloader实现动态服务加载。

Java 9 的模块系统中,uses 声明用于表明当前模块**消费(使用)某个服务接口**,即它依赖该服务的实现,但不提供实现本身。这是服务发现机制的关键一环,配合 provides…with(在提供方模块中声明)和 ServiceLoader 运行时加载共同工作。
uses 声明的作用和位置
uses 必须写在模块的 module-info.java 文件中,位于 module 块内。它只声明“我需要这个服务”,不指定具体实现类,也不导入包——实现类由运行时通过 ServiceLoader.load() 动态查找。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 声明格式:
uses com.example.MyService; - 服务类型必须是接口或抽象类(通常为接口)
- 模块无需直接依赖提供该服务的具体实现模块,只需依赖定义服务接口的模块
完整服务消费流程示例
假设有一个日志服务接口 LoggerService,定义在 com.example.logging 模块中:
- 消费者模块(如
app.module)在module-info.java中写:
uses com.example.logging.LoggerService; - 同时,该模块需
requires com.example.logging;(因为要用到接口类型) - 在代码中用
ServiceLoader.load(LoggerService.class)获取实例 - 运行时 JVM 会扫描所有模块的
provides声明,找到匹配的实现并加载
注意事项和常见误区
-
uses不会自动触发类加载,只是编译期和运行期的服务契约声明 - 如果没有任何模块提供该服务,
ServiceLoader返回空迭代器,不会报错——需代码中判空处理 - 不能在同一个模块中既
uses又provides同一个服务(除非有意做代理或装饰,但非常规用法) - 服务接口所在的模块不需要
uses自己——只有消费者才需要声明
与 requires 的区别
requires 表示对另一个模块的**强静态依赖**(编译和运行都必需),而 uses 是一种**弱动态依赖**:只表示“我打算用这个服务”,实际实现可能在启动时才注入,甚至可插拔替换。
- 例如:模块 A
requires B→ A 直接调用 B 中的 public 类和方法 - 模块 C
uses X+requires D(D 定义了 X 接口)→ C 通过ServiceLoader调用 X 的实现,实现可能来自模块 E、F 或测试时的 Mock 模块
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










