包可见性与 JPMS 模块化:从 package 边界到运行期反射与服务治理
大约 2 分钟
包可见性与 JPMS 模块化:从 package 边界到运行期反射与服务治理
新手先看 · 一屏速览
- 同包内可见(package-private)是“缩小暴露面”的利器
- 模块化(Java 9+):
module-info.java声明exports/requires,限制可见性边界 - 反射在强模块化下可能受限,需要
opens/--add-opens等显式开放
1. 包与可见性
- public:所有可见;protected:包内 + 子类;(default):仅包内;private:类内部
- 工程建议:将内部实现保持包私有,对外仅暴露契约与入口 实战:将“仓储实现/DTO 转换器”等实现类放在
internal包并保持包私有,防止不当耦合
2. 模块化基础
module com.example.app {
requires com.fasterxml.jackson.databind;
exports com.example.api;
opens com.example.internal to com.fasterxml.jackson.databind;
}exports控制对外可见的包;opens放宽运行时反射访问
补充:
- 模块路径(modulepath)与类路径(classpath)不可随意混用;未命名模块(Unnamed Module)在类路径上
- 自动模块(Automatic Module):jar 无 module-info,放到模块路径会被推导模块名,谨慎使用
3. 服务发现(ServiceLoader)
ServiceLoader<MySpi> loader = ServiceLoader.load(MySpi.class);
for (MySpi spi : loader) spi.run();- 模块化下用
provides ... with ...与uses声明服务提供与使用
module com.example.spi {
exports com.example.spi;
uses com.example.spi.Spi;
}
module com.example.impl {
requires com.example.spi;
provides com.example.spi.Spi with com.example.impl.RealSpi;
}4. 反射与可访问性
最近建一些几十个工作内推群,各大城市都有,群里目前已经收集了很多内推岗位,大厂、中厂、小厂、外包都有。 欢迎HR、开发、测试、运维和产品加入。

扫描下方微信,备注:网站+所在城市,即可拉你进工作内推群。

- 强模块化限制了非法反射;框架在运行时需要
opens或命令行--add-opens - 建议:在 module-info 明确开放范围,避免全局放开
5. 分层 ClassLoader 与隔离
- 插件化/容器化场景:自定义 ClassLoader 隔离不同模块依赖
- 结合模块化与类加载隔离,强化运行时边界与安全
6. 实战清单与反模式
- 清单:优先包私有;模块化明确 exports/opens;服务声明配合 ServiceLoader
- 反模式:一股脑 public;在模块化下依赖非法反射;未管理对外 API 边界
7. 练习
- 为一个多包工程设计 module-info,划清对外/对内边界
- 为反射需求最小化开放范围,并验证运行时行为
