应用架构与模块化单体:先学会维护一个单体
当订单逻辑散落在很多包里,改一个字段都要搜索半个项目时,就该重新考虑代码如何组织。模块化首先是让相关业务待在一起,并限制互相访问的方式;它不要求你立刻拆服务。
版本与资料依据
last_verified:2026-08-24version_scope:Spring Modulith current conceptssource_type:Spring official docs + architecture literaturestability:version-sensitive
核心问题不是记 DDD 名词,而是:业务边界如何划分,使代码、事务、测试和团队协作长期可维护。
flowchart LR
W[Web Adapter] --> A[Application Service]
A --> D[Domain Model/Service]
D --> R[Repository Port]
R --> I[Persistence Adapter]
A --> E[Domain Event]
E --> O[Outbox/Event Publication]
学习顺序
- package by layer 与 package by feature 的依赖差异;
- domain model、bounded context 基础与语言边界;
- application service 编排 use case,domain service 放置跨实体规则;
- repository 是领域所需持久化边界,不等于每表一个 DAO;
- ports & adapters 让业务规则不依赖 HTTP/DB;
- module verification 与 module integration test;
- transaction boundary、domain event、outbox、idempotency;
- 用 observability 看模块交互,再决定是否拆服务。
先画谁能访问谁,再画目录
从订单、库存两个功能开始:订单模块可以请求库存预留,但不能随意修改库存内部表或读取它的内部仓库类。先列出允许的调用,再把需要公开的参数和结果写成接口。
练习时故意增加一个反向依赖,让库存也直接依赖订单内部实现,观察模块验证是否拒绝。练习的重点是把约定变成可检查的规则;一个漂亮的目录树不会自动阻止跨模块访问。
本节的核验依据
2026-10-25 查阅。下面的链接支持本节的机制说明;练习场景和选型建议是本教程的教学设计。
