很多系统一开始写得挺顺,功能也能交付,问题往往出在两三轮迭代之后。人多了、需求多了,代码开始“到处都能调用到处”,公共包越来越厚,改动影响范围越来越难判断。你如果不想立刻把系统拆成一堆微服务去背新的运维成本,又确实需要把结构拉回可控状态,模块化单体会是一个更贴近现实的选项。Spring Modulith做的事情很直接:它帮你把单体内部的模块边界说清楚、守住,并把这件事变成可以被验证的工程规则。
一、Spring Modulith模块化单体是什么
Spring Modulith可以理解为给Spring Boot单体加上一套模块化治理能力,让系统仍然是一个部署单元,但内部不再靠“大家自觉”维持秩序。它更关注结构和边界,目的是让单体在继续变大的时候,依赖关系不会继续失控。
1、它强调单体仍然一次发布一次部署
你不会因为引入它就立刻多出注册中心、网关、分布式配置那一整套东西,日常交付方式基本不变,改造压力也更可控。
2、它把业务能力拆成应用模块来管理
模块划分建议按业务域来做,比如订单、库存、结算各自一块,不是按Controller、Service、DAO这种技术分层去堆目录。模块更像一个业务单元,有自己的入口,也有自己的内部实现。
3、它把模块之间的依赖关系变成可检查的约束
单体最怕的就是模块互相绕着引用,最后出现依赖环。Spring Modulith会把越界依赖暴露出来,让问题在构建或测试阶段就能被发现,而不是线上才靠事故提醒。
4、它让模块协作更容易走“规矩路”
跨模块协作更推荐通过清晰入口完成,或者用事件表达业务事实,减少那种顺手去调用别人内部类的情况。这样你在重构某个模块内部实现时,不容易把其他模块一并拖下水。
5、它把模块化从目录整理变成长期可维护的做法
很多人做模块化只是重排包结构,过一阵子又乱回去。Spring Modulith更强调把规则放进日常流程里,让模块边界能长期守住,这才是它真正值钱的地方。
二、Spring Modulith模块化单体适合哪些项目
它适不适合,关键看你们是不是正被单体复杂度拖慢,又暂时不想承担微服务的额外运行成本。更直白一点:你们现在最痛的是结构混乱和改动失控,还是资源隔离和独立扩缩容。如果前者更痛,模块化单体往往更合适。
1、业务复杂度上来了,但还没到非拆微服务不可
系统开始出现连锁影响,改一个小功能要翻半天依赖,回归测试也越来越心虚。这类项目先做模块边界收敛,收益通常来得很快。
2、多人并行开发,同一代码库里“越界引用”管不住
靠评审去抓每一次跨模块引用很难,时间久了公共包会变成垃圾场。把边界做成规则以后,团队协作会更清楚:谁负责什么,哪些东西能被调用,哪些只能在模块内部使用。
3、系统交付节奏紧,但平台化能力还不够
你们可能没有专门的平台团队去维护微服务底座,也不想为了拆分先把基础设施重做一遍。模块化单体能先把内部治理做起来,尽量不动外部运行环境。
4、业务边界还在变化期,直接拆服务风险很高
边界没稳定就拆服务,最容易拆错,拆错后回头成本更大。先在单体里按模块沉淀边界,等边界清晰了再考虑服务化,会更踏实。
5、存量单体已经有明显退化迹象,想做“渐进式体检和修复”
公共包膨胀、领域对象到处漂、模块之间互相抄近路,这些都适合用模块化单体做收敛。它更像一把尺子,让你知道哪里越界了,改造也能按模块逐步推进。
6、不适合的情况也要提前识别
如果你已经明确要独立扩缩容、独立发布节奏、强资源隔离,或者系统天然是多语言多栈并行,那模块化单体很可能只能做短期过渡。这个前提不讲清楚,后面容易对它产生不切实际的期待。
三、Spring Modulith模块化单体怎么落地
落地最怕两件事:一是一次性大改,搞得团队停工;二是只改目录,不改行为,过两个月又回到原样。比较稳的方式是从试点开始,把规则跑通,把校验放进流程,再逐步扩大范围。
1、先选一条最“闹心”的业务链做试点
不要从全局重排开始,优先选改动最频繁、牵连最广的链路,把相关能力围成一个模块,先做到外部只能通过入口访问。
2、把模块入口收敛成少量明确的对外能力
对外暴露的类越多,边界越难守。入口可以是门面服务、应用服务或少量对外接口,其他实现尽量留在模块内部,避免外部直接依赖内部细节。
3、把跨模块调用的规则写清楚
哪些模块允许依赖哪些模块,哪些协作必须走入口,哪些更适合用事件通知,先形成团队共识。规则越清晰,后面越不容易靠“顺手”把边界磨平。
4、把结构校验放进测试或构建流程
模块化不是一次性清理,而是长期治理。只要有人越界,校验就应该在开发阶段直接把问题挡住,否则边界迟早会被写回去。
5、围绕模块入口补一组能代表真实调用的测试
不需要追求覆盖面夸张,但要覆盖关键输入输出和典型失败路径。入口稳了,模块内部重构就不会每次都靠胆子大。
6、把公共包当作重点治理对象
公共包最好保持“真通用”,带业务语义的工具类和规则尽量回到所属模块。公共包越瘦,系统的耦合度就越容易下降,改动影响范围也更好判断。
总结
Spring Modulith的价值不在于把单体包装成“像微服务”,而在于让单体在继续演进时仍然有边界、有规则、有抓手。它适合那些已经感到单体越来越重、越来越乱,但短期又不想把系统拆成一堆服务去增加运维负担的团队。先从一个模块试点,把入口收敛,把校验进流程,系统结构会慢慢变得更清楚,后续无论继续做模块化还是走服务化,都会更从容。