Spring Modulith:企业级模块化单体架构的权威深度研究报告
-
执行摘要:架构的理性回归与模块化单体的复兴
在过去十年中,企业软件架构领域经历了一场深刻的变革。微服务架构曾被视为解决所有扩展性和敏捷性问题的灵丹妙药,导致无数组织在未能充分评估其运维复杂性的情况下盲目拆分单体应用。这种趋势往往导致了“分布式单体(Distributed Monolith)”反模式的出现,即系统虽然在物理上是分布式的,但在逻辑上依然紧密耦合,同时引入了网络延迟、分布式事务难题以及高昂的运维成本 。
Spring Modulith 应运而生,它不仅仅是一个技术框架,更代表了架构设计哲学的一种理性回归。作为 Spring 生态系统中的一个重要项目,Spring Modulith 旨在帮助开发者构建结构良好、领域驱动的模块化单体应用(Modular Monolith)。它通过在单个部署单元(JAR)内强制执行严格的逻辑边界,提供了一种“中间地带”的架构选择:既拥有单体应用的部署简便性和事务一致性,又具备微服务架构的代码组织和解耦优势。
本报告将对 Spring Modulith 进行详尽的深度剖析。我们将从其历史渊源与“Moduliths”实验项目的关系入手,深入探讨其核心的结构验证机制、复杂的事件驱动架构支持(特别是事务性发件箱模式的实现)、自动化文档生成能力,以及针对遗留系统的迁移策略。通过对大量技术文档和社区实践的综合分析,
本报告旨在为架构师和高级开发人员提供一份关于如何利用 Spring Modulith 构建可持续演进的企业级系统的权威指南。
-
架构背景与演进:从泥球模式到结构化治理
2.1 “大泥球”困境与微服务的反思
在传统的 Spring Boot 单体应用开发中,缺乏结构性的约束往往导致系统演变为“大泥球(Big Ball of Mud)”。随着业务需求的增长,原本清晰的包结构逐渐崩塌,不同业务领域的代码相互缠绕。例如,订单服务(Order Service)可能直接注入库存仓储(Inventory Repository)并调用用户工具类(User Utility),形成错综复杂的依赖网状结构 ()。
这种紧密耦合带来了极其严重的后果:
-
脆弱性(Fragility): 对用户模块内部逻辑的微小修改,可能意外导致订单处理流程的崩溃,因为两者在代码层面缺乏隔离。
-
认知负荷(Cognitive Load): 新加入团队的开发者无法区分哪些类是模块的公开 API,哪些是内部实现细节,导致错误地依赖了本应隐藏的内部组件。
-
重构瘫痪(Refactoring Paralysis): 当系统最终需要拆分为微服务时,由于依赖关系过于混乱,剥离任何一个业务领域都变得几乎不可能,往往只能选择高风险的重写 ()。
微服务架构试图通过物理隔离(不同的进程、不同的代码库)来解决这一问题。然而,这种物理隔离带来了巨大的代价:网络通信的不稳定性、数据一致性的丧失以及基础设施管理的复杂性。许多团队发现,他们并没有解决耦合问题,只是将进程内的函数调用变成了脆弱的 HTTP 请求,从而构建了一个更难维护的分布式系统 ()。
2.2 Spring Modulith 的诞生与定位
Spring Modulith 是 Oliver Drotbohm 发起的实验性项目“Moduliths”(带有一个尾随的 's')的继任者 ()。该项目最初旨在探索在 Spring 生态系统中如何克服 Java 平台模块系统(JPMS)的局限性,提供更好的逻辑模块化支持。JPMS 虽然提供了强封装,但其基于 JAR 文件的物理模块化要求复杂的构建描述符,且与 Spring 的动态特性(如类扫描、AOP)整合时存在诸多摩擦 ()。
Spring Modulith 摒弃了 JPMS 强制物理分离的路径,转而专注于逻辑层面的模块化。它通过分析代码结构和运行时元数据,在单个 Spring Boot 应用内部划定清晰的“应用模块(Application Modules)”边界。2022年,该项目被正式纳入 Spring 官方投资组合,并在 Spring Boot 3.0 的基础上重构为 "Spring Modulith",标志着其已成熟并准备好用于生产环境 ()。它的核心理念是:模块化应当是架构的首要属性,而是否分布式部署则是次要的运维决策 ()。
-
核心概念与分类学体系
Spring Modulith 引入了一套特定的分类学体系来描述应用的结构。深入理解这些定义是有效实施该框架的前提。
3.1 应用模块(Application Module)的定义
在 Spring Modulith 的语境下,应用模块是功能的逻辑单元,由应用主包(Main Package)下的直接子包表示。这与 Maven 或 Gradle 的构建模块不同,它完全基于 Java 的包结构 ()。
假设一个标准的 Spring Boot 应用结构如下:
-
主包:
com.acme.shop(包含@SpringBootApplication启动类) -
库存模块:
com.acme.shop.inventory -
订单模块:
com.acme.shop.orders -
客户模块:
com.acme.shop.customers
在这种结构中,任何位于 com.acme.shop 直系下属的包(如 inventory、orders)都会被自动识别为一个独立的“应用模块”。这种约定优于配置(Convention over Configuration)的设计,使得开发者无需编写繁琐的 XML 或注解即可定义模块边界 ()。
3.2 封装与可见性规则(Encapsulation)
Java 语言本身的包可见性(Package-Private)在处理多层级包结构时显得力不从心。Spring Modulith 引入了更高级的封装规则,以弥补语言层面的不足。
-
公开 API(Provided Interface): 默认情况下,Spring Modulith 将位于模块根包(例如
com.acme.shop.inventory)下的类型(类、接口、记录)视为该模块的公开 API。这些类型允许被其他模块引用 ()。 -
内部实现(Internal Implementation): 任何位于模块子包(例如
com.acme.shop.inventory.internal或com.acme.shop.inventory.service)中的类型,均被视为模块的私有实现细节。Spring Modulith 严格禁止其他模块访问这些类型 ()。
这一机制至关重要。它允许开发者将某些类声明为 public,以便 Spring 框架进行实例化和依赖注入(DI),同时在架构层面禁止其他业务模块“看到”或使用这些类。这实际上创造了一种由工具强制执行的“模块私有(Module-Private)”作用域,防止了内部实现细节的泄漏 ()。
3.3 命名接口(Named Interfaces)
在复杂的业务领域中,简单地将根包作为唯一 API 可能过于粗放。一个模块可能需要向不同的消费者暴露不同的功能切片。为了支持接口隔离原则(ISP),Spring Modulith 引入了 命名接口 的概念。
开发者可以通过 @NamedInterface 注解,显式定义模块 API 的一个子集。
场景示例: 假设 Inventory(库存)模块需要向 Order(订单)模块暴露库存检查功能,但向 Admin(管理)模块暴露库存调整功能。
package com.acme.shop.inventory;
@NamedInterface("availability-check")
public interface StockChecker {
boolean inStock(ProductId id);
}
此时,Order 模块可以在其 package-info.java 中声明仅依赖于 inventory::availability-check,从而在架构层面明确了它只能调用库存检查功能,而无法调用库存调整逻辑。这极大地细化了模块间的依赖契约 ()。
3.4 开放与封闭模块(Open vs. Closed Modules)
默认情况下,所有模块都是“封闭”的,即隐藏其子包内容。然而,在遗留系统迁移等特殊场景下,立即强制执行严格封装可能会导致大量编译错误。为此,Spring Modulith 允许将模块声明为“开放”。
在 package-info.java 中进行如下配置:
@org.springframework.modulith.ApplicationModule(type = Type.OPEN)
package com.acme.shop.legacy;
标记为 OPEN 的模块允许其他模块访问其所有内部类型(包括子包)。这虽然违背了模块化的初衷,但作为一种过渡手段(Release Valve),它允许团队在不破坏现有功能的前提下逐步引入 Modulith 的验证机制,随后再逐个收紧模块边界 ()。
-
结构验证与静态分析
上述架构规则的执行不再依赖于开发者的自律或代码审查,Spring Modulith 提供了一套基于测试的自动化验证工具,将架构治理纳入了持续集成(CI)流程。
4.1 ApplicationModules API 的工作原理
ApplicationModules 类是验证系统的核心。该 API 会扫描整个应用程序的类路径,解析包结构、分析 Spring Bean 的依赖关系图以及事件监听器的连接情况,从而构建出一个完整的应用模块模型 ()。
验证过程通常集成在一个标准的 JUnit 测试中:
class ModularityTests {
@Testvoid
verifyModularity() {
ApplicationModules.of(Application.class).verify();
}
}
当运行此测试时,Spring Modulith(内部利用 ArchUnit 库)会执行以下关键检查:
-
循环依赖检测(Cyclic Dependencies): 确保模块之间不存在循环引用(例如:模块 A 依赖 模块 B,模块 B 又依赖 模块 A)。这是保持系统可维护性的底线 ()。
-
内部访问违规(Internal Access Violations): 扫描所有类引用,确保没有模块试图导入另一个模块的内部子包中的类。
-
显式依赖校验(Explicit Dependency Violations): 如果模块在
package-info.java中通过allowedDependencies属性声明了允许的依赖列表,验证器将确保该模块没有与未声明的模块发生交互 ()。
4.2 集成 ArchUnit 与 jMolecules
Spring Modulith 与 jMolecules 库深度集成,支持更高级的领域驱动设计(DDD)规则验证。例如,开发者可以强制实施六边形架构(Hexagonal Architecture)或洋葱架构的约束。
六边形架构验证示例:
var hexagonal = JMoleculesArchitectureRules.ensureHexagonal(VerificationDepth.STRICT);
var options = VerificationOptions.defaults().withAdditionalVerifications(hexagonal);
ApplicationModules.of(Application.class).verify(options);
这段代码确保了领域层(Domain Layer)不依赖于基础设施适配器(Infrastructure Adapters),强制执行了依赖倒置原则。这种能力使得架构风格不再是口头约定,而是可执行的代码约束 ()。
4.3 运行时反馈与 IDE 集成
除了在测试阶段进行验证,JetBrains 的 IntelliJ IDEA(Ultimate 版)已经内置了对 Spring Modulith 的支持。IDE 能够识别模块边界,并在编辑器中实时标记违规引用(例如,当开发者试图自动导入一个内部类时,IDE 会发出警告或拒绝补全)。这种“左移”的反馈机制极大地提高了开发效率,防止架构违规代码进入代码库 ()。
-
事件驱动架构(EDA)与模块间通信
虽然结构验证防止了“错误”的耦合,但 Spring Modulith 真正的威力在于它积极鼓励“正确”的解耦方式——事件驱动架构。这是该框架技术含量最高、最具创新性的部分。
5.1 从方法调用转向事件发布
在单体应用中,模块间交互的最简单方式是直接方法调用(Direct Method Call)。例如,OrderService 注入 InventoryService 并调用 updateStock()。
-
优点: 简单直观,事务 ACID 特性由数据库天然保证。
-
缺点: 导致强耦合。如果库存服务响应缓慢,订单服务也会变慢;如果库存服务抛出异常,订单事务即回滚。两个领域的生命周期被绑定在了一起 ()。
Spring Modulith 提倡使用 Spring 应用程序事件(Application Events)来替代非必要的直接调用。OrderService 不再调用库存服务,而是发布一个 OrderCompletedEvent。InventoryService 监听该事件并作出反应。这种依赖倒置(Inversion of Control)使得库存模块依赖于订单事件,而不是订单模块依赖于库存 API ()。
5.2 双写问题(The Dual-Write Problem)与事务完整性
在传统的 Spring 事件机制中,如果使用同步监听器(Synchronous Listener),监听器逻辑会在同一个事务中执行。这虽然保证了一致性,但无法实现性能隔离。如果开发者转向 @Async 异步监听器以提高性能,则会遭遇著名的 双写问题(Dual-Write Problem):
-
订单数据写入数据库。
-
事件消息发送到内存队列(或消息中间件)。
-
场景 A: 数据库事务提交成功,但在事件发送前系统崩溃。结果:订单已创建,但库存从未扣减。
-
场景 B: 事件发送成功,但随后的数据库提交失败(回滚)。结果:库存被扣减,但订单并不存在 ()。
这种不一致性在金融或电商系统中是不可接受的。
5.3 事务性发件箱模式(Transactional Outbox)的透明实现
Spring Modulith 通过在框架层面透明地实现 事务性发件箱模式,完美解决了上述难题。
当一个标记为 @Transactional 的业务方法发布事件时,Spring Modulith 会介入该过程:
-
拦截与持久化: 框架不会立即广播事件,而是将事件序列化(JSON),并在同一个数据库事务中将其写入一个专用的
EVENT_PUBLICATION表 ()。 -
原子性提交: 由于业务数据写入和事件日志写入发生在同一事务中,它们要么同时成功,要么同时回滚。这保证了业务状态与事件发布状态的原子一致性。
-
异步执行: 事务提交后,Spring Modulith 会尝试触发监听器。
-
如果监听器执行成功,
EVENT_PUBLICATION表中的对应记录会被标记为“已完成(Completed)” ()。 -
如果监听器执行失败,该记录保持“未完成”状态。
-
-
故障恢复: 系统启动时或通过后台定时任务,Spring Modulith 会扫描所有未完成的事件记录并重新投递。这确保了在单体应用内部的 至少一次投递(At-Least-Once Delivery) 语义 ()。
5.4 事件发布注册表(Event Publication Registry)
负责管理这一生命周期的子系统称为 事件发布注册表。它支持多种持久化技术,包括 JPA、JDBC、MongoDB 和 Neo4j ()。
5.4.1 数据库架构规范
对于关系型数据库(JPA/JDBC),框架需要一张特定的表(默认为 EVENT_PUBLICATION)。该表的标准 Schema 设计至关重要,直接影响性能和兼容性:
| 字段名 | 类型 (SQL标准) | 描述 |
| ID | VARCHAR(36) / UUID | 事件发布的唯一标识符。 |
| EVENT_TYPE | VARCHAR(512) | 事件类的全限定名。 |
| SERIALIZED_EVENT | TEXT / VARCHAR(MAX) | 序列化后的事件 Payload(通常为 JSON)。 |
| PUBLICATION_DATE | TIMESTAMP | 事件创建时间。 |
| COMPLETION_DATE | TIMESTAMP | 监听器成功执行的时间(未完成为 NULL)。 |
| LISTENER_ID | VARCHAR(512) | 目标监听器的唯一标识。 |
注意: 对于 SQL Server、PostgreSQL 或 MySQL,必须确保 SERIALIZED_EVENT 列能够存储大文本数据,否则在处理复杂事件时会抛出截断错误 ()。
5.4.2 注册表配置与优化
开发者需引入相应的 Starter 依赖,如 spring-modulith-starter-jpa。 关键配置项包括:
-
spring.modulith.events.republish-outstanding-events-on-restart:控制应用启动时是否立即重试未完成事件(默认为true) ()。 -
spring.modulith.events.jdbc.schema-initialization.enabled:是否自动创建数据库表(生产环境建议通过 Flyway/Liquibase 管理,测试环境可设为true) ()。
5.5 事件外部化(Event Externalization)
除了内部模块解耦,现代系统通常需要与外部系统(如数据湖、CRM、第三方 API)通信。Spring Modulith 提供了 事件外部化 机制,简化了这一流程。
开发者无需手动编写 KafkaTemplate 发送代码,只需在事件类上添加注解:
@Externalized("orders.topic")
public record OrderPlacedEvent(UUID orderId) {
}
Spring Modulith 会自动检测此注解,并创建一个适配器监听器:
-
监听内部 Spring 事件。
-
将事件转换为消息格式。
-
发送到配置的消息代理(Kafka、RabbitMQ/AMQP 或 JMS) ()。
这一过程同样受到事件发布注册表的保护。消息只有在本地事务提交后才会发送到 Kafka,确保外部系统永远不会收到“脏读”事件(即对应事务已回滚的事件) ()。
高级配置:
-
路由目标(Routing Targets): 支持 SpEL 表达式动态计算。例如:
@Externalized("target::#{#this.customerId()}")可以使用客户 ID 作为 Kafka 的 Partition Key ()。 -
依赖支持: 需要引入
spring-modulith-events-kafka或spring-modulith-events-amqp()。
-
测试策略:模块隔离集成测试
在一个模块化的单体中,测试策略必须尊重模块的边界。传统的 @SpringBootTest 会启动整个应用上下文,速度慢且无法验证模块间的隔离性;单元测试虽快,却无法验证组件装配。Spring Modulith 引入了 @ApplicationModuleTest 来填补这一空白。
6.1 @ApplicationModuleTest 的核心机制
当在测试类上使用 @ApplicationModuleTest 时,框架会执行特殊的引导程序:
-
上下文裁剪: 仅启动当前被测模块包含的 Bean。
-
自动 Mock: 自动 Mock 掉该模块所依赖的其他模块的 Bean ()。
这种“独立(Standalone)”模式迫使开发者明确模块的依赖关系,并确保模块能够在隔离环境中运行。如果模块 A 隐式依赖了模块 B 的数据库表,这种测试会立即失败,从而暴露耦合问题。
6.2 引导模式(Bootstrap Modes)
@ApplicationModuleTest 支持多种引导模式,以适应不同的测试需求:
-
STANDALONE(默认): 仅加载当前模块,Mock 所有外部依赖。最严格,速度最快。 -
DIRECT_DEPENDENCIES: 加载当前模块及其直接依赖的模块。用于测试紧密协作的模块组。 -
ALL_DEPENDENCIES: 加载整个应用结构,但依然保持对当前模块的关注。类似于@SpringBootTest,但在结构验证上有优势 ()。
6.3 场景 API(Scenario API)
测试事件驱动的逻辑通常非常痛苦:测试代码触发动作后,不得不通过 Thread.sleep() 或轮询来等待异步事件的处理结果。Spring Modulith 提供了一套优雅流畅的 Scenario API 来解决此问题。
@Testvoid
testingEventFlow(Scenario scenario) {
scenario.publish(new OrderCreatedEvent(...))
.andWaitForStateChange(() -> orderRepository.count())
.expectResult(count -> count == 1);
}
该 API 内部封装了复杂的超时处理、事务管理和断言逻辑,使得异步集成测试变得像同步代码一样可读且确定 ()。
-
文档即代码(Documentation as Code)
软件架构中的一个永恒难题是文档滞后于实现。Wiki 页面和架构图往往在代码修改的那一刻就过时了。Spring Modulith 通过直接从代码生成文档彻底解决了这个问题。
7.1 Documenter API
框架包含一个 Documenter 类,它利用 ApplicationModules 提取的模型数据生成可视化和文本化文档。
@Testvoid
generateDocs() {
ApplicationModules modules = ApplicationModules.of(Application.class);
new Documenter(modules) .writeDocumentation().writeIndividualModulesAsPlantUml();
}
7.2 生成产物详解
这一过程会生成以下关键资产:
-
C4 组件图(Component Diagrams): 展示模块间交互(依赖、事件流)的高层视图。生成为 PlantUML (
.puml) 文件,可自动渲染为 PNG/SVG 图片 ()。 -
应用模块画布(Application Module Canvas): 每个模块的表格化概览,列出其包含的 Spring Bean、聚合根(Aggregate Roots)、发布及监听的事件、以及配置属性 ()。
-
AsciiDoc 片段: 文本化的依赖描述,可以直接嵌入到项目的 AsciiDoc 文档(如 Spring REST Docs)中,生成完整的开发者手册 ()。
这种“活文档(Living Documentation)”方法确保了架构图永远反映代码的真实状态——因为每次运行测试时,文档都会被重新生成 ()。
-
深度对比分析:单体、模块化单体与微服务
为了从战略高度理解 Spring Modulith 的价值,我们需要将其与传统单体和微服务进行多维度的对比。
| 特性维度 | 传统单体 (Classic Monolith) | 模块化单体 (Spring Modulith) | 微服务 (Microservices) |
| 部署单元 | 单个 JAR (简单) | 单个 JAR (简单) | 多个容器/Pod (复杂) |
| 逻辑边界 | 弱 / 易被破坏 | 强 / 工具强制执行 | 强 / 网络物理隔离 |
| 通信方式 | 直接方法调用 | 方法调用 + 内部事件 | REST / gRPC / 消息队列 |
| 事务一致性 | ACID (简单可靠) | ACID + 最终一致性 (Outbox) | Saga / 分布式事务 (极难) |
| 重构难度 | 困难 (意大利面条代码) | 容易 (边界预先定义) | 困难 (需 API 版本管理) |
| 扩展性 | 仅垂直扩展 | 垂直扩展 (部分异步处理) | 水平扩展 (独立扩缩容) |
| 运维成本 | 低 | 低 / 中 | 高 (K8s, Service Mesh) |
| 适用团队 | < 10人 | 5 - 50人 | > 50人 / 多语言团队 |
深度洞察: Spring Modulith 占据了一个独特的“黄金中间地带”。它允许团队像构建微服务一样构建代码(有界上下文、事件驱动、严格封装),但以单体的简单形式进行部署。这实际上推迟了引入分布式系统高昂成本的时间点,直到业务规模真正需要为止 ()。
何时选择 Spring Modulith?
-
团队规模适中(5-25名开发人员) ()。
-
业务领域复杂,但吞吐量或扩展性需求不需要物理分片。
-
数据强一致性优于最终一致性。
-
正在对遗留的“大泥球”系统进行治理 ()。
何时迁移到微服务?
-
特定模块需要完全不同的硬件配置(例如:一个模块需要 GPU 计算,另一个需要大内存)。
-
团队规模扩展至无法有效协同(50+人),需要完全独立的部署周期 ()。
-
多语言技术栈需求(如 Python AI 模块与 Java 后端配合) ()。
-
迁移战略:从遗留代码到 Modulith
将遗留的混乱代码重构为 Spring Modulith 是一个非琐碎但高回报的过程。基于社区最佳实践,我们提出以下分阶段迁移战略。
第一阶段:评估与发现(Assessment & Discovery)
在移动任何代码之前,首先要利用 ApplicationModules 对现有代码库进行分析。即使测试失败,生成的依赖图也能清晰地展示当前的循环依赖热点(Hotspots)。识别应用中的自然“接缝(Seams)”——即那些总是协同变化的类簇。
第二阶段:包结构重组(Package Realignment)
-
物理移动: 摒弃按技术分层(
controllers,services,repositories)的打包方式,转向按业务领域打包(billing,shipping,catalog)。这是领域驱动设计(DDD)的基础 ()。 -
消除循环: 这是最困难的一步。如果
Billing依赖Shipping,而Shipping又依赖Billing,必须引入接口抽象或使用事件机制来切断其中一个方向的依赖。
第三阶段:引入 Modulith 强制器(Enforcers)
-
添加 Spring Modulith 依赖。
-
创建
verify()测试。此时它几乎肯定会失败。 -
“开放模块”战术: 为了不阻塞开发,将所有遗留包标记为
@ApplicationModule(type = Type.OPEN)()。这相当于承认技术债务,但允许验证基础设施到位。 -
制定计划,逐个移除
OPEN标记,收紧边界。
第四阶段:事件驱动重构(Event-Driven Refactoring)
-
识别服务方法中的副作用(例如:“下订单后发送邮件”)。
-
将这些副作用提取为事件监听器。
-
启用事件发布注册表,确保重构过程不会引入数据丢失风险 ()。
第五阶段:封闭与接口定义(Closing & Interface Definition)
-
将模块内部的类改为包可见(Package-Private)。
-
利用
@NamedInterface仅暴露必要的 API ()。 -
最终目标是所有模块均为
CLOSED状态,且验证测试全绿。
-
高级配置与内部机制
10.1 定制事件注册表
对于高并发应用,默认的 EVENT_PUBLICATION 表可能会迅速膨胀。
-
完成模式(Completion Mode): 可通过
spring.modulith.events.completion-mode配置。-
UPDATE(默认):仅更新时间戳。保留历史记录,需手动清理。 -
DELETE:成功后立即删除行。保持表体量小,节省空间,但丢失审计轨迹 ()。 -
ARCHIVE:将完成的事件移动到归档表,兼顾性能与审计 ()。
-
10.2 异步性能与线程池
默认情况下,事件发布注册表使用 Spring 标准的 TaskExecutor。在负载较重时,建议配置专用的 ThreadPoolTaskExecutor 用于事件监听器,以防止事件处理线程耗尽,影响 Web 请求处理线程 ()。
10.3 可观测性(Observability)
Spring Modulith 与 Spring Boot Actuator 和 Micrometer 深度集成。它暴露了丰富的指标:
-
事件发布的成功/失败率。
-
模块间交互的时延分布。
-
注册表积压(Backlog)大小。 这使得运维团队能够像监控微服务一样,监控逻辑模块的健康状况和性能瓶颈 ()。
-
结论
Spring Modulith 代表了 Java 生态系统的成熟。它承认“单体”并非贬义词,混乱无序的单体才是。通过提供标准化、有观点且由工具强制执行的结构,它使团队能够构建复杂、可扩展且易于维护的系统。
它具有双重战略价值:
-
作为终点: 对于绝大多数企业应用,模块化单体是最具成本效益和性能优势的架构。Spring Modulith 使这种架构在长期演进中保持可持续性。
-
作为桥梁: 对于真正需要微服务的应用,Spring Modulith 确保了应用是经过预先切分的。“拆分单体”不再是一个需要数年时间的重写项目,而变成了将独立模块部署为独立进程的简单运维操作。
在 2026 年及未来,利用 Spring Modulith 不仅是编写代码,更是在购买未来的“架构期权”——既保留了当下的简单性,又为未来的复杂性做好了准备。对于任何新的 Spring Boot 项目,这无疑是值得推荐的默认架构选择。
更多推荐




所有评论(0)