若依项目做到第三个月admin 模块越来越臃肿——启动 40 秒、改一行代码全量编译、两个人改同一个文件天天冲突。这篇文章复盘我是怎么把若依从单模块拆成多模块的哪个先拆、边界怎么画、依赖怎么管、趟过的坑一个不落。一、单体项目的三个月魔咒最开始搭若依的时候目录干净得让人舒服ruoyi-admin/ ├── src/main/java/com/ruoyi/ │ ├── controller/ ← 用户、角色、菜单、工单、客户... │ ├── service/ ← 所有业务逻辑 │ ├── mapper/ ← 所有数据库映射 │ └── ... └── pom.xml前两周没毛病改什么都快。代码生成器一键出 CRUD一天能上两张表。问题从第一个月开始冒头症状具体表现谁难受启动变慢从 8 秒涨到 40 秒每次调试都等得心烦编译范围大改一行 Service全量 300 类重新编译浪费时间合并冲突两个人都在admin里加东西每天 merge 都有冲突协作成本飙升边界模糊CRM 的 Service 和 MES 的 Service 混在一起越写越不敢删谁敢重构谁死到第二个月底ruoyi-admin已经塞了 CRM 模块和 MES 模块的全部代码——Controller 40 多个Service 30 多个Mapper 50 多个。每次 IDE 里打开项目树要滚好几页才能找到想看的文件。单模块不坏但当你开始纠结这个类该放哪个包的时候就是该拆的时候了。二、若依框架的模块化设计全景先看若依官方给的标准模块结构这对理解后面的拆分至关重要ruoyi/ ├── ruoyi-common/ # 公共工具类、异常、注解、枚举 ├── ruoyi-framework/ # 框架核心配置安全、数据源、Swagger ├── ruoyi-system/ # 系统管理业务用户、角色、菜单、部门 ├── ruoyi-generator/ # 代码生成器 ├── ruoyi-quartz/ # 定时任务 └── ruoyi-admin/ # 启动模块 Controller 汇总2.1 各模块的职责与边界模块职责可以依赖谁被谁依赖ruoyi-common工具类、通用异常、基础注解、常量无最底层所有模块ruoyi-framework安全配置、数据源配置、全局拦截器ruoyi-commonruoyi-system、ruoyi-adminruoyi-system用户/角色/菜单/部门等系统管理业务ruoyi-common、ruoyi-frameworkruoyi-adminruoyi-generator代码生成器ruoyi-commonruoyi-adminruoyi-quartz定时任务管理ruoyi-commonruoyi-adminruoyi-admin启动类、全局 Controller、静态资源以上所有无顶层2.2 核心原则依赖只向下若依的依赖链路是一条单向链ruoyi-admin ──→ ruoyi-system ──→ ruoyi-framework ──→ ruoyi-common 顶层 业务层 配置层 基础层没有任何一个底层模块依赖上层模块。这是 Maven 多模块拆分的第一铁律。如果你想不明白这个原则记住一句土话common 不能 import 任何业务代码framework 不关心具体业务system 只管自己的表。三、实战第一步把业务模块从 admin 里拆出来3.1 拆之前的状态在我们项目里ruoyi-admin底下实际长这样ruoyi-admin/src/main/java/com/ruoyi/ ├── web/controller/system/ ← 若依自带的系统管理 ├── web/controller/crm/ ← CRM客户、联系人、商机... ├── web/controller/mes/ ← MES工单、工序、质检... ├── service/system/ ├── service/crm/ ├── service/mes/ ├── mapper/system/ ├── mapper/crm/ └── mapper/mes/包名分开了但物理上全在一个模块。只要改一行整个模块重新编译。这跟没拆没区别。3.2 怎么拆别贪多一次只拆一个模块。我先拆的是 CRM因为它和若依自带的系统管理耦合最小。Step 1创建新模块在根pom.xml的modules里加一行!-- 根 pom.xml -- modules moduleruoyi-common/module moduleruoyi-framework/module moduleruoyi-system/module moduleruoyi-generator/module moduleruoyi-quartz/module moduleruoyi-admin/module moduleruoyi-crm/module !-- 新增 -- /modules新建ruoyi-crm目录里面放一个pom.xml!-- ruoyi-crm/pom.xml -- parent groupIdcom.ruoyi/groupId artifactIdruoyi/artifactId version3.3.0/version /parent artifactIdruoyi-crm/artifactId nameruoyi-crm/name dependencies !-- 只依赖 common 和 system不依赖 admin -- dependency groupIdcom.ruoyi/groupId artifactIdruoyi-common/artifactId /dependency dependency groupIdcom.ruoyi/groupId artifactIdruoyi-system/artifactId /dependency /dependencies⚠️ 关键ruoyi-crm不要依赖ruoyi-admin。admin 是顶层业务模块不能反向依赖。Step 2迁移代码目录结构对齐到标准的 Maven 模块目录ruoyi-crm/ ├── pom.xml └── src/main/java/com/ruoyi/crm/ ├── controller/ ← 从 admin 搬过来的 ├── service/ ├── service/impl/ ├── mapper/ └── domain/ ← entity 放这按住 IDE 的拖拽把 CRM 相关的包整个拖到ruoyi-crm/src/main/java/com/ruoyi/crm/下。注意包路径变了原来com.ruoyi.web.controller.crm→ 现在com.ruoyi.crm.controller。所有 import 语句需要同步修改IDE 的批量替换可以搞定大部分。Step 3admin 加上依赖!-- ruoyi-admin/pom.xml -- dependency groupIdcom.ruoyi/groupId artifactIdruoyi-crm/artifactId /dependency这样ruoyi-admin启动时才会把ruoyi-crm的类扫进 Spring 容器。MES 模块同理再建一个ruoyi-mes操作完全一样。3.3 第一个坑Spring Boot 扫描不到 Bean代码搬过去依赖加好启动——报了一堆NoSuchBeanDefinitionException。原因若依的启动类在com.ruoyi包下SpringBootApplication默认只扫描启动类所在包及其子包。CRM 代码移到了com.ruoyi.crm下还在com.ruoyi子包里所以理论上扫得到。但我踩的坑是有些代码路径习惯性写成了com.ruoyi.web.controller.crm搬家后变成了com.ruoyi.crm.controller中间的web层级没了包结构发生变化。而原来admin里有些地方的MapperScan还是指向老路径。解决统一把MapperScan放到各模块各自的配置类里不要全堆在 admin 中// ruoyi-crm 模块中 Configuration MapperScan(com.ruoyi.crm.mapper) public class CrmConfig { }这样每个模块管好自己的 Mapper 扫描admin 不用操心。四、实战第二步公共代码怎么不重复——common 的演进4.1 什么时候抽到 common拆完 CRM 和 MES 后很快发现一个问题两个模块都需要 Excel 导出工具ExcelUtil。最蠢的做法各 copy 一份。等你改了 bug 忘了同步另一份线上就出灵异事件。正确做法抽到ruoyi-commonruoyi-common/src/main/java/com/ruoyi/common/utils/ ├── ExcelUtil.java ← CRM 和 MES 都用 ├── PageUtils.java ← 通用分页工具 └── DictUtils.java ← 字典工具抽取原则很简单该放 common不该放 common所有业务模块都用的分页、导出、日期工具只有两个模块共用的业务 DTO异常类、枚举、基础注解跟某个具体业务强绑定的工具全局常量临时性、可能随时变的配置4.2 什么时候不该放 commonCRM 和 MES 之间有一个共享场景MES 的质检模块需要查 CRM 的客户信息。我们就建了一个CrmCustomerBriefDTO用于跨模块传递。这个 DTO 如果放ruoyi-common就会导致 common 开始膨胀——今天塞一个客户 DTO明天塞一个工单 DTO最终 common 又变成了大杂烩。方案建一个ruoyi-shared-dto模块只放跨模块共享的数据对象!-- ruoyi-shared-dto/pom.xml -- dependencies dependency groupIdcom.ruoyi/groupId artifactIdruoyi-common/artifactId /dependency /dependencies然后 CRM 和 MES 都依赖它。common 保持干净。common 的使命是基础能力不是业务共享。业务共享另有其位。五、实战第三步多模块下的配置管理5.1 每个模块能各配各的吗不能。Spring Boot 在启动时只会加载一次application.yml——默认从classpath下找具体位置是启动类所在模块的resources目录。其他模块的application.yml不会被自动合并。所以正确的做法是所有全局配置都放在ruoyi-admin/src/main/resources/下。5.2 那模块的专属配置怎么办用ConfigurationProperties 配置前缀隔离// ruoyi-crm 模块中 Data Component ConfigurationProperties(prefix crm) public class CrmConfig { /** 客户导入最大行数 */ private int importMaxRows 5000; /** 商机过期天数 */ private int opportunityExpireDays 30; }对应在ruoyi-admin的application.yml中# application.yml只在 admin 中维护 crm: import-max-rows: 5000 opportunity-expire-days: 30 mes: work-order-prefix: WO quality-check-levels: IPQC,IPFQC,FQC每个模块内部注入自己的配置类互不干扰。5.3 多环境配置多模块下的多环境配置跟单模块没区别仍然用spring.profiles.activeruoyi-admin/src/main/resources/ ├── application.yml ← 公共配置 ├── application-dev.yml ← 开发环境 ├── application-test.yml ← 测试环境 └── application-prod.yml ← 生产环境启动时指定--spring.profiles.activedev核心原则不变所有 yml 文件都放在ruoyi-admin的 resources 里业务模块只定义ConfigurationProperties类。六、Maven 多模块构建与打包6.1 统一版本号拆了多模块后最怕版本号散落各处。Maven 的dependencyManagement是救命稻草!-- 根 pom.xml -- properties ruoyi.version3.3.0/ruoyi.version mybatis-plus.version3.5.5/mybatis-plus.version hutool.version5.8.28/hutool.version /properties dependencyManagement dependencies !-- 内部模块版本统一 -- dependency groupIdcom.ruoyi/groupId artifactIdruoyi-common/artifactId version${ruoyi.version}/version /dependency !-- 外部依赖版本统一 -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version${mybatis-plus.version}/version /dependency /dependencies /dependencyManagement子模块引用时不写版本号由根 pom 统一管控!-- ruoyi-crm/pom.xml -- dependency groupIdcom.ruoyi/groupId artifactIdruoyi-common/artifactId !-- 版本号继承根 pom 的 dependencyManagement -- /dependency6.2 打包产物在根目录执行mvn clean package最终在ruoyi-admin/target/下生成一个可执行 jar。所有子模块的 class 都被打包进去了部署时只需要一个 jar 文件。6.3 第二个大坑循环依赖拆 MES 模块的时候我遇到过CRM 需要一个方法来查客户名称 → 我直接在 MES 的 Service 里注入 CRM 的 Service。反过来CRM 有一段逻辑需要调 MES 的工单状态我又在 CRM 里注入了 MES 的 Service。结果Maven 编译直接报错Circular dependency。正确的解法CRM ←→ MES 互调的场景 → 提取共享接口到 ruoyi-common// ruoyi-common 中定义接口 public interface CustomerBriefService { CustomerBriefDTO getBrief(Long customerId); } // ruoyi-crm 中实现接口 Service public class CustomerBriefServiceImpl implements CustomerBriefService { // 实现从 CRM 数据库查客户简要信息 } // ruoyi-mes 中依赖接口不依赖实现 Service public class QualityCheckService { Autowired private CustomerBriefService customerBriefService; // 注入接口 }Spring 会自动找到ruoyi-crm中的实现并注入。MES 只依赖 common 中的接口不依赖 CRM 模块本身——循环依赖就这样解了。七、拆分后的最终架构拆完后的项目结构ruoyi/ ├── ruoyi-common/ # 工具类、异常、基础注解 ├── ruoyi-framework/ # 安全、数据源、全局配置 ├── ruoyi-system/ # 系统管理用户、角色、菜单 ├── ruoyi-crm/ # CRM 业务模块 ├── ruoyi-mes/ # MES 业务模块 ├── ruoyi-shared-dto/ # 跨模块共享 DTO ├── ruoyi-generator/ # 代码生成器 ├── ruoyi-quartz/ # 定时任务 └── ruoyi-admin/ # 启动模块拆分后的实际收益维度拆之前拆之后启动时间~40 秒~18 秒只改了 CRM 时热加载更快编译时间改一行全量 300 类只编译当前模块代码冲突天天 merge 冲突基本不冲突各改各的模块新人上手要弄懂整个 admin 才能改读懂一个模块就能开工删除成本不敢删怕影响别处Maven 依赖关系图一眼看穿敢删八、总结 核心原则回顾这次拆分我一直遵循三条原则① 依赖只向下。底层模块永远不依赖上层admin 依赖一切common 不依赖任何业务。② 公共代码提 common业务代码放模块。common 是基础能力集不是垃圾桶。③ 一次只拆一个模块。不要想着一次拆干净——拆一个跑通再拆下一个。稳定压倒一切。什么时候该拆如果你对下面三个问题有两个回答是就该动手了启动时间超过 30 秒两个人以上在同一个模块里写代码你开始纠结这个类到底该放哪个包什么时候先别拆项目还在 Demo 阶段业务都不确定只有你一个人写而且一个月内不会加人代码量不到 100 个类拆分是为协作和长期维护服务的不要为了拆而拆。如果你也在独立开发产品或者对制造业数字化感兴趣欢迎关注这个公众号。我会持续分享从代码到产品的全过程——包括成功的经验也包括踩过的坑。一个人的产品之路不孤单。原创作者 MqCode全栈开发者印刷包装行业 MESCRM 系统独立开发欢迎自由转发。
若依多模块 Maven 项目架构实战:从单体到模块化
若依项目做到第三个月admin 模块越来越臃肿——启动 40 秒、改一行代码全量编译、两个人改同一个文件天天冲突。这篇文章复盘我是怎么把若依从单模块拆成多模块的哪个先拆、边界怎么画、依赖怎么管、趟过的坑一个不落。一、单体项目的三个月魔咒最开始搭若依的时候目录干净得让人舒服ruoyi-admin/ ├── src/main/java/com/ruoyi/ │ ├── controller/ ← 用户、角色、菜单、工单、客户... │ ├── service/ ← 所有业务逻辑 │ ├── mapper/ ← 所有数据库映射 │ └── ... └── pom.xml前两周没毛病改什么都快。代码生成器一键出 CRUD一天能上两张表。问题从第一个月开始冒头症状具体表现谁难受启动变慢从 8 秒涨到 40 秒每次调试都等得心烦编译范围大改一行 Service全量 300 类重新编译浪费时间合并冲突两个人都在admin里加东西每天 merge 都有冲突协作成本飙升边界模糊CRM 的 Service 和 MES 的 Service 混在一起越写越不敢删谁敢重构谁死到第二个月底ruoyi-admin已经塞了 CRM 模块和 MES 模块的全部代码——Controller 40 多个Service 30 多个Mapper 50 多个。每次 IDE 里打开项目树要滚好几页才能找到想看的文件。单模块不坏但当你开始纠结这个类该放哪个包的时候就是该拆的时候了。二、若依框架的模块化设计全景先看若依官方给的标准模块结构这对理解后面的拆分至关重要ruoyi/ ├── ruoyi-common/ # 公共工具类、异常、注解、枚举 ├── ruoyi-framework/ # 框架核心配置安全、数据源、Swagger ├── ruoyi-system/ # 系统管理业务用户、角色、菜单、部门 ├── ruoyi-generator/ # 代码生成器 ├── ruoyi-quartz/ # 定时任务 └── ruoyi-admin/ # 启动模块 Controller 汇总2.1 各模块的职责与边界模块职责可以依赖谁被谁依赖ruoyi-common工具类、通用异常、基础注解、常量无最底层所有模块ruoyi-framework安全配置、数据源配置、全局拦截器ruoyi-commonruoyi-system、ruoyi-adminruoyi-system用户/角色/菜单/部门等系统管理业务ruoyi-common、ruoyi-frameworkruoyi-adminruoyi-generator代码生成器ruoyi-commonruoyi-adminruoyi-quartz定时任务管理ruoyi-commonruoyi-adminruoyi-admin启动类、全局 Controller、静态资源以上所有无顶层2.2 核心原则依赖只向下若依的依赖链路是一条单向链ruoyi-admin ──→ ruoyi-system ──→ ruoyi-framework ──→ ruoyi-common 顶层 业务层 配置层 基础层没有任何一个底层模块依赖上层模块。这是 Maven 多模块拆分的第一铁律。如果你想不明白这个原则记住一句土话common 不能 import 任何业务代码framework 不关心具体业务system 只管自己的表。三、实战第一步把业务模块从 admin 里拆出来3.1 拆之前的状态在我们项目里ruoyi-admin底下实际长这样ruoyi-admin/src/main/java/com/ruoyi/ ├── web/controller/system/ ← 若依自带的系统管理 ├── web/controller/crm/ ← CRM客户、联系人、商机... ├── web/controller/mes/ ← MES工单、工序、质检... ├── service/system/ ├── service/crm/ ├── service/mes/ ├── mapper/system/ ├── mapper/crm/ └── mapper/mes/包名分开了但物理上全在一个模块。只要改一行整个模块重新编译。这跟没拆没区别。3.2 怎么拆别贪多一次只拆一个模块。我先拆的是 CRM因为它和若依自带的系统管理耦合最小。Step 1创建新模块在根pom.xml的modules里加一行!-- 根 pom.xml -- modules moduleruoyi-common/module moduleruoyi-framework/module moduleruoyi-system/module moduleruoyi-generator/module moduleruoyi-quartz/module moduleruoyi-admin/module moduleruoyi-crm/module !-- 新增 -- /modules新建ruoyi-crm目录里面放一个pom.xml!-- ruoyi-crm/pom.xml -- parent groupIdcom.ruoyi/groupId artifactIdruoyi/artifactId version3.3.0/version /parent artifactIdruoyi-crm/artifactId nameruoyi-crm/name dependencies !-- 只依赖 common 和 system不依赖 admin -- dependency groupIdcom.ruoyi/groupId artifactIdruoyi-common/artifactId /dependency dependency groupIdcom.ruoyi/groupId artifactIdruoyi-system/artifactId /dependency /dependencies⚠️ 关键ruoyi-crm不要依赖ruoyi-admin。admin 是顶层业务模块不能反向依赖。Step 2迁移代码目录结构对齐到标准的 Maven 模块目录ruoyi-crm/ ├── pom.xml └── src/main/java/com/ruoyi/crm/ ├── controller/ ← 从 admin 搬过来的 ├── service/ ├── service/impl/ ├── mapper/ └── domain/ ← entity 放这按住 IDE 的拖拽把 CRM 相关的包整个拖到ruoyi-crm/src/main/java/com/ruoyi/crm/下。注意包路径变了原来com.ruoyi.web.controller.crm→ 现在com.ruoyi.crm.controller。所有 import 语句需要同步修改IDE 的批量替换可以搞定大部分。Step 3admin 加上依赖!-- ruoyi-admin/pom.xml -- dependency groupIdcom.ruoyi/groupId artifactIdruoyi-crm/artifactId /dependency这样ruoyi-admin启动时才会把ruoyi-crm的类扫进 Spring 容器。MES 模块同理再建一个ruoyi-mes操作完全一样。3.3 第一个坑Spring Boot 扫描不到 Bean代码搬过去依赖加好启动——报了一堆NoSuchBeanDefinitionException。原因若依的启动类在com.ruoyi包下SpringBootApplication默认只扫描启动类所在包及其子包。CRM 代码移到了com.ruoyi.crm下还在com.ruoyi子包里所以理论上扫得到。但我踩的坑是有些代码路径习惯性写成了com.ruoyi.web.controller.crm搬家后变成了com.ruoyi.crm.controller中间的web层级没了包结构发生变化。而原来admin里有些地方的MapperScan还是指向老路径。解决统一把MapperScan放到各模块各自的配置类里不要全堆在 admin 中// ruoyi-crm 模块中 Configuration MapperScan(com.ruoyi.crm.mapper) public class CrmConfig { }这样每个模块管好自己的 Mapper 扫描admin 不用操心。四、实战第二步公共代码怎么不重复——common 的演进4.1 什么时候抽到 common拆完 CRM 和 MES 后很快发现一个问题两个模块都需要 Excel 导出工具ExcelUtil。最蠢的做法各 copy 一份。等你改了 bug 忘了同步另一份线上就出灵异事件。正确做法抽到ruoyi-commonruoyi-common/src/main/java/com/ruoyi/common/utils/ ├── ExcelUtil.java ← CRM 和 MES 都用 ├── PageUtils.java ← 通用分页工具 └── DictUtils.java ← 字典工具抽取原则很简单该放 common不该放 common所有业务模块都用的分页、导出、日期工具只有两个模块共用的业务 DTO异常类、枚举、基础注解跟某个具体业务强绑定的工具全局常量临时性、可能随时变的配置4.2 什么时候不该放 commonCRM 和 MES 之间有一个共享场景MES 的质检模块需要查 CRM 的客户信息。我们就建了一个CrmCustomerBriefDTO用于跨模块传递。这个 DTO 如果放ruoyi-common就会导致 common 开始膨胀——今天塞一个客户 DTO明天塞一个工单 DTO最终 common 又变成了大杂烩。方案建一个ruoyi-shared-dto模块只放跨模块共享的数据对象!-- ruoyi-shared-dto/pom.xml -- dependencies dependency groupIdcom.ruoyi/groupId artifactIdruoyi-common/artifactId /dependency /dependencies然后 CRM 和 MES 都依赖它。common 保持干净。common 的使命是基础能力不是业务共享。业务共享另有其位。五、实战第三步多模块下的配置管理5.1 每个模块能各配各的吗不能。Spring Boot 在启动时只会加载一次application.yml——默认从classpath下找具体位置是启动类所在模块的resources目录。其他模块的application.yml不会被自动合并。所以正确的做法是所有全局配置都放在ruoyi-admin/src/main/resources/下。5.2 那模块的专属配置怎么办用ConfigurationProperties 配置前缀隔离// ruoyi-crm 模块中 Data Component ConfigurationProperties(prefix crm) public class CrmConfig { /** 客户导入最大行数 */ private int importMaxRows 5000; /** 商机过期天数 */ private int opportunityExpireDays 30; }对应在ruoyi-admin的application.yml中# application.yml只在 admin 中维护 crm: import-max-rows: 5000 opportunity-expire-days: 30 mes: work-order-prefix: WO quality-check-levels: IPQC,IPFQC,FQC每个模块内部注入自己的配置类互不干扰。5.3 多环境配置多模块下的多环境配置跟单模块没区别仍然用spring.profiles.activeruoyi-admin/src/main/resources/ ├── application.yml ← 公共配置 ├── application-dev.yml ← 开发环境 ├── application-test.yml ← 测试环境 └── application-prod.yml ← 生产环境启动时指定--spring.profiles.activedev核心原则不变所有 yml 文件都放在ruoyi-admin的 resources 里业务模块只定义ConfigurationProperties类。六、Maven 多模块构建与打包6.1 统一版本号拆了多模块后最怕版本号散落各处。Maven 的dependencyManagement是救命稻草!-- 根 pom.xml -- properties ruoyi.version3.3.0/ruoyi.version mybatis-plus.version3.5.5/mybatis-plus.version hutool.version5.8.28/hutool.version /properties dependencyManagement dependencies !-- 内部模块版本统一 -- dependency groupIdcom.ruoyi/groupId artifactIdruoyi-common/artifactId version${ruoyi.version}/version /dependency !-- 外部依赖版本统一 -- dependency groupIdcom.baomidou/groupId artifactIdmybatis-plus-boot-starter/artifactId version${mybatis-plus.version}/version /dependency /dependencies /dependencyManagement子模块引用时不写版本号由根 pom 统一管控!-- ruoyi-crm/pom.xml -- dependency groupIdcom.ruoyi/groupId artifactIdruoyi-common/artifactId !-- 版本号继承根 pom 的 dependencyManagement -- /dependency6.2 打包产物在根目录执行mvn clean package最终在ruoyi-admin/target/下生成一个可执行 jar。所有子模块的 class 都被打包进去了部署时只需要一个 jar 文件。6.3 第二个大坑循环依赖拆 MES 模块的时候我遇到过CRM 需要一个方法来查客户名称 → 我直接在 MES 的 Service 里注入 CRM 的 Service。反过来CRM 有一段逻辑需要调 MES 的工单状态我又在 CRM 里注入了 MES 的 Service。结果Maven 编译直接报错Circular dependency。正确的解法CRM ←→ MES 互调的场景 → 提取共享接口到 ruoyi-common// ruoyi-common 中定义接口 public interface CustomerBriefService { CustomerBriefDTO getBrief(Long customerId); } // ruoyi-crm 中实现接口 Service public class CustomerBriefServiceImpl implements CustomerBriefService { // 实现从 CRM 数据库查客户简要信息 } // ruoyi-mes 中依赖接口不依赖实现 Service public class QualityCheckService { Autowired private CustomerBriefService customerBriefService; // 注入接口 }Spring 会自动找到ruoyi-crm中的实现并注入。MES 只依赖 common 中的接口不依赖 CRM 模块本身——循环依赖就这样解了。七、拆分后的最终架构拆完后的项目结构ruoyi/ ├── ruoyi-common/ # 工具类、异常、基础注解 ├── ruoyi-framework/ # 安全、数据源、全局配置 ├── ruoyi-system/ # 系统管理用户、角色、菜单 ├── ruoyi-crm/ # CRM 业务模块 ├── ruoyi-mes/ # MES 业务模块 ├── ruoyi-shared-dto/ # 跨模块共享 DTO ├── ruoyi-generator/ # 代码生成器 ├── ruoyi-quartz/ # 定时任务 └── ruoyi-admin/ # 启动模块拆分后的实际收益维度拆之前拆之后启动时间~40 秒~18 秒只改了 CRM 时热加载更快编译时间改一行全量 300 类只编译当前模块代码冲突天天 merge 冲突基本不冲突各改各的模块新人上手要弄懂整个 admin 才能改读懂一个模块就能开工删除成本不敢删怕影响别处Maven 依赖关系图一眼看穿敢删八、总结 核心原则回顾这次拆分我一直遵循三条原则① 依赖只向下。底层模块永远不依赖上层admin 依赖一切common 不依赖任何业务。② 公共代码提 common业务代码放模块。common 是基础能力集不是垃圾桶。③ 一次只拆一个模块。不要想着一次拆干净——拆一个跑通再拆下一个。稳定压倒一切。什么时候该拆如果你对下面三个问题有两个回答是就该动手了启动时间超过 30 秒两个人以上在同一个模块里写代码你开始纠结这个类到底该放哪个包什么时候先别拆项目还在 Demo 阶段业务都不确定只有你一个人写而且一个月内不会加人代码量不到 100 个类拆分是为协作和长期维护服务的不要为了拆而拆。如果你也在独立开发产品或者对制造业数字化感兴趣欢迎关注这个公众号。我会持续分享从代码到产品的全过程——包括成功的经验也包括踩过的坑。一个人的产品之路不孤单。原创作者 MqCode全栈开发者印刷包装行业 MESCRM 系统独立开发欢迎自由转发。