渐进式迁移是类路径转向模块路径最稳妥方式,分四阶段:一、确保JDK9+类路径无警告运行;二、单模块试点,精准exports/opens;三、切断隐式变量传递,改用SPI或工厂;四、通过编译报错、jdeps和IllegalAccessError验证解耦落地。
渐进式迁移是从类路径转向模块路径最稳妥的方式,它不追求一步到位,而是分阶段引入模块约束,让变量作用域、包可见性和依赖关系逐步收口,从而实质性降低因随意暴露内部状态引发的解耦风险。
阶段一:先跑通,再模块化
确保项目能在 JDK 9+ 上以纯类路径方式无警告运行。重点处理三类问题:
- 替换已废弃的 API(如 java.security.acl、javax.xml.bind)
- 统一第三方库版本,避免同一类在多个 JAR 中重复出现
- 禁用隐式反射调用——例如 Spring 的
setAccessible(true)若未声明opens,会在模块化后直接失败
阶段二:单模块试点,锁定变量边界
选一个核心但不被广泛反射调用的模块(如业务规则引擎或配置中心),为其添加 module-info.java:
- 只 exports 明确需要被其他模块使用的接口包(如
com.example.rule.api),绝不导出impl或internal - 对需反射访问的包,用 opens 替代 exports(如
opens com.example.rule.internal to spring.core;) - 将模块内所有“跨包访问的私有变量”改为封装为 getter/setter,并检查调用方是否越界依赖实现类
阶段三:切断隐式传递,显式控制变量流向
模块化后,变量不再靠“类能加载到就能用”来流通,而必须通过导出包 + 接口契约来传递。此时要主动干预三类高危模式:
- 删除
public static final全局配置变量,改用 服务提供者接口(SPI) 或依赖注入获取 - 禁止跨模块直接 new 实例;所有共享变量应通过
requires声明依赖 +exports接口 + 工厂方法交付 - 检查
requires transitive使用场景——仅当本模块对外暴露的 API 类型来自所依赖模块时才加,否则会把变量可见性无意扩大
阶段四:验证解耦有效性
迁移不是写完 module-info.java 就结束。用以下方式确认变量解耦真正落地:
- 编译时报错替代运行时异常:比如把某 impl 类从
exports移除后,原调用代码应立即编译失败,而非静默使用 - 用
jdeps --list-deps --module-path mods/ myapp.jar查看实际依赖图,确认没有意外的跨模块字段引用 - 运行时尝试访问未导出包中的 public 字段——JVM 应抛出
IllegalAccessError,而非返回值

















