把 DDD 写进业务代码,
而不是写进架构图里
soda 为 Spring Boot 而生的企业级 DDD / CQRS 框架。四层架构、命令查询分离、领域事件、上下文全链路传递 —— 一个 starter 依赖就能起步。
这是什么
soda 不是一个"分层规范文档",而是一组已经在跑的代码。你引入依赖,写一个聚合根和一个 CommandHandler,框架的切面会自动把上下文带进领域事件、串起命令链路、并在递归发生时把请求掐断。
命令与查询分开
写操作走 Command → CommandHandler → 聚合根 → 仓储,读操作走 Query → QueryHandler → 读库。两条链路各自独立演进,天然避免「一个方法又读又写」。
聚合根自己发事件
领域事件由聚合根在状态变更时产生(addPendingEvent),而不是由 Service 层手动 new。事件和状态变更天然同源。
上下文全链路传递
requestId、用户身份、租户、权限随命令进入聚合根、写进领域事件、跨服务投递时一路带着,异步链路也不会断。
递归保护
同步调用有 10 层深度上限,异步事件有 20 跳 hopCount 上限。事件互相触发形成死循环时,请求会带着可读的报错停下来,而不是打满 CPU。
四层架构,边界严格
第一天就为你生成好 —— 此后一直被守住。每个文件都有唯一的家:动一处依赖,只有一个层会受影响。
依赖方向怎么定的、每层能依赖谁,见 核心概念。
恰到好处的框架分量
DDD 需要的构件都在,多余的都没有 —— 不强加事件溯源的存储税。
与典型的 DDD 框架比一比:
| 对比项 | soda | 典型 DDD 框架 |
|---|---|---|
| 学习曲线 | ● 简单 | ●● 中等 |
| 事件溯源 | 可扩展支持 | 完整支持 |
| 存储效率 | ● 高效 | ●● 需优化 |
| 查询性能 | ● 快速 | ●● 需优化 |
| 调试难度 | ● 简单 | ●● 中等 |
| AI 辅助开发 | ● 内置 CLAUDE.md | ○ 少见 |
soda 的取舍很直白:读模型为查询提速,写模型守好业务规则;持久化保持克制,不默认事件溯源。落到代码里怎么写,见 写一个命令。
一次请求走完全程
这是 soda 最值得理解的一件事:一个 HTTP 请求从进来到返回,中间发生了什么。 先看全景,再看细节。
Controller 收到请求
你写的普通 Spring MVC Controller。ControllerAroundHandler(可选)从请求头读出 Soda-Request-Id 和 Soda-User-Name,写进 MDC 和命令对象。
命令进总线
busFacade.sendCommand(cmd) 把命令交给 CommandBus,总线按泛型类型找到对应的 CommandHandler Bean。
切面搬运上下文
CqrsAroundHandler 的 @Around 把命令里的 requestId / 用户 / 租户写进 ThreadLocal(DomainEventContext),供后面取用。
CommandHandler 执行领域逻辑
你的 CommandHandler 调聚合根方法,聚合根改状态并 addPendingEvent(...) 挂上领域事件 —— 事件此刻自动被注入上下文。
仓储保存
writeRepository.save(domain)。保存时 RepositoryEventAspect 拦截,把挂起的事件取出来发布到事件总线。
事件驱动下游
EventHandler(事件 Handler)收到事件做后续动作(发消息、发通知、写读库)。用 Simple 总线就是进程内,用 Redis 总线就是跨服务。
统一返回
CommandHandler 返回 DTO,切面兜底异常:BaseException 映射成 Result.fail(code, message),其它异常统一成「系统内部错误」,不泄漏内部细节。
完整拆解见 请求是怎么跑完的。
该从哪儿开始
版本与坐标
本文档与 soda-core 发版同步,坐标里的版本号在构建时自动填入。最新版本以 Maven 仓库为准 —— 详见 版本与兼容。
<dependency>
<groupId>com.hibuka.soda</groupId>
<artifactId>soda-core-base</artifactId>
<version>17.0.1</version>
</dependency>需要跨服务事件总线时,再加一个可选依赖:
<dependency>
<groupId>com.hibuka.soda</groupId>
<artifactId>soda-event-redis</artifactId>
<version>17.0.1</version>
</dependency>仓库地址:github.com/chenkangzeng1/soda-core。示例工程可以直接抄 —— 站内 工程结构 一节给了完整目录树。