运行时依赖
无特殊依赖
版本
latestv1.0.0
Decision Tree
安装命令
点击复制官方npx clawhub@latest install java-circular-dependency-breaker
镜像加速npx clawhub@latest install java-circular-dependency-breaker --registry https://cn.longxiaskill.com 镜像可用
本土化适配说明
java-circular-dependency-breaker — Java循环依赖破解器 安装说明: 安装命令:["openclaw skills install java-circular-dependency-breaker"]
技能文档
Java 循环依赖破解器 两套经实战验证的模式,用于打破 Gradle 或 Maven 多模块项目中的循环依赖。
何时启用
- Gradle 多模块出现
api project(':module-a')↔api project(':module-b')循环 - Maven 出现
module-a循环 - 将单体模块拆小且不改现有代码
- 服务类跨模块迁移,但调用方仍引用具体实现
- 某类方法同时依赖两模块服务,无法直接迁移
设计模式 采用 Mediator Pattern:引入中间层(接口或业务服务)解耦。 模式1:服务接口作中介,调用方仅依赖抽象。 模式2:服务层作中介,协调跨模块逻辑,不重复数据访问,保持原类纯净。
要求 JDK 8+(需 javap)、Gradle 或 Maven、Git(可回滚)
开始前检查点 0
- 找出导致循环的具体类
./gradlew :module-a:dependencies --configuration compileClasspath | grep module-b
Maven: mvn dependency:tree -pl module-a | grep module-b
- 确认至少被外部模块引用(否则直接移动,无需接口)
- 全模块编译通过、测试全绿
- 阅读下方决策树选模式
⚠️ 暂停并询问用户:
- 类 public 方法 >20(建议先拆分)
- 类在 5+ 测试文件中被 mock(迁移成本高)
- 循环涉及 3+ 模块(可能需顺序应用模式)
模式1:接口抽取 适用:Module A 引用 Module B 的具体类,且该类方法无跨模块依赖。
前置
- 输入:Module B 中带
@Service/@Component的具体类,被 Module A 引用 - 约束:public 方法不得依赖 Module A 的服务/类
- 耗时:≤10 个 public 方法约 15–30 min
- 风险:低,编译器可验证
步骤
- 在共享模块(或新建 *-interface 模块)创建接口
IXxxService(或项目规范)
检查点1:接口方法是原类 public 方法真子集;返回/参数类型不依赖源模块;javap -public 对比无误 - 目标模块实现接口
implements IXxxService,保留 @Service/@Component
检查点2::module-b:compileJava 通过;Spring 无 bean 冲突 - 源模块所有调用方改为接口
IXxxService
检查点3:源模块无剩余具体类 import;测试 mock 改为 @Mock IBeanName - 移除源模块对目标模块的依赖
api project(':module-b'),保留 api project(':module-interface')
Maven:删对应 块
检查点4::module-a:compileJava、:module-a:compileTestJava 通过;依赖树不再出现 module-b ⚠️ 编译失败:先恢复依赖,修完再删,禁止留破窗。
示例 // 前 @Service public class OrderService { private final NotificationService notificationService; // 具体类 }
// 后 public interface INotificationService { ... }