exports to 是 java 9+ 模块系统中实现定向包可见性的机制,需同时满足提供方 exports to、消费方 requires、包内类为 public 三条件;它区别于普通 exports 的广播式开放,支持最小权限控制与零信任实践。

用 exports to 限定导出范围
Java 9 模块系统支持将某个包仅导出给特定模块,而不是对所有依赖者开放。这通过 exports
为什么不能只靠普通 exports
普通 exports com.example.api; 表示该包对**所有显式 requires 当前模块的其他模块**可见。但如果你只想让模块 A 使用这个包,而模块 B 即使也 requires 当前模块也不应访问它,普通 exports 就无法满足——它不具备“白名单”能力。
- 未加 to 的 exports 是“公开但需主动依赖”的策略
- 加了 to 的 exports 是“仅限指定模块访问”的策略
- 两者都要求调用方必须在自己的 module-info.java 中写 requires,否则编译直接失败
实际写法与注意事项
假设你有一个工具模块 com.example.utils,其中 com.example.utils.internal 包只允许被 com.example.app 使用:
module com.example.utils {
exports com.example.utils.internal to com.example.app;
exports com.example.utils.api; // 公共 API 对所有依赖者开放
}
- to 后只能跟模块名,不能是包名或通配符
- 如果目标模块名拼错,编译器会报错:“module not found in the module graph”
- 被导出的包内类仍需是 public 的,否则即使导出也无法访问
- 该语法不支持反射穿透(如想让 Spring 访问某包,要用 opens to,不是 exports to)
常见误用场景提醒
有人试图用 exports to 实现“SPI 接口的第三方实现”,这是错误的。例如:
// ❌ 错误:把 SPI 接口只导出给主模块,第三方模块无法实现它
module com.example.spi {
exports com.example.spi to com.example.app;
}
这样会导致第三方模块(如 com.thirdparty.impl)即使声明了 requires com.example.spi,也会因包不可见而编译失败。SPI 场景应使用无限制 exports,由 requires 控制接入权,而非 exports to 限制实现权。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











