Spring Boot六边形架构下适配器依赖关系设计问题
六边形架构与DDD重构下外部服务适配器设计方案
项目背景
- 重构目标:让项目完全符合六边形架构与*领域驱动设计(DDD)*的规范要求
- 领域层拆分:目前按实体维度拆分为文件、客户数据两类业务实体,拆分逻辑具备合理性
- 现有标准调用链路:
Controller(应用层) → 调用Facade(门面) → 调用Ports(端口) → 由Adapters(适配器,归属基础设施层)实现端口对应逻辑 - 当前进度:已完成File相关模块开发,CustomerData模块重构尚未启动

待解决的核心问题
- 系统存在一个未纳入现有结构图的外部OCR服务,通过
Feign客户端对接其API,该服务的能力同时覆盖两个现有本地适配器的业务范畴:- 可输出客户数据,匹配第一个本地适配器的业务边界
- 可输出图像原始数据,匹配第二个本地适配器的业务边界
- 两个现有本地适配器均配套对应的本地实体、
Repository与数据库存储 - 具体设计疑问:
- 按照六边形架构核心原则,外部OCR服务本应作为独立适配器存在,但拆分后两个本地适配器该如何调用这个OCR适配器?
- 是否因为OCR适配器和两个本地适配器存在能力重叠,且CustomerData与File本身存在一对多关联,就需要将三者合并为同一个适配器?
- 现有参考资料的局限:多数技术文章示例过于简化,仅演示业务域完全拆分的简单场景,缺乏生产环境复杂依赖场景的可落地实践参考。
设计方案与核心结论
不需要合并三个适配器,OCR服务作为独立基础设施适配器存在即可,严格禁止适配器之间直接产生调用关系。
核心设计原则依据
六边形架构的核心边界规则非常明确:
- 端口的职责定义归属领域层,完全不关心后续由谁实现
- 适配器仅负责对接具体的外部依赖(数据库、第三方API、消息队列等),实现对应端口的契约
- 所有跨组件的流程编排逻辑,统一放在
Facade层或者领域服务层完成,适配器层只做单一的“外部交互”逻辑,不承载任何编排、跨域调用的职责 - 领域实体之间的关联关系(比如CustomerData和File的一对多关系)属于领域层逻辑,绝对不能下沉到基础设施适配器层做耦合
可直接落地的实现步骤
- 先对齐端口定义,完全不考虑后续适配器的实现逻辑:
- 在客户数据域定义
CustomerDataProvider端口,声明获取、持久化客户数据的所有相关接口 - 在文件域定义
FileRawDataProvider端口,声明获取、存储文件原始数据的所有相关接口
- 在客户数据域定义
- 独立实现OCR适配器:
- 在基础设施层新建独立的OCR适配器模块,内部封装所有
Feign调用逻辑、参数转换、异常兜底、重试、熔断逻辑 - 这个适配器可以同时实现上面定义的两个端口中,和OCR能力匹配的方法(比如从OCR接口获取识别出的客户数据、从OCR接口获取上传的图像原始数据),不需要为了“一个适配器只对应一个端口”的错误认知强行拆分OCR服务的逻辑
- 在基础设施层新建独立的OCR适配器模块,内部封装所有
- 保持两个本地适配器的独立性:
- 两个对接本地数据库的适配器,只需要实现两个端口中和本地存储交互的方法(比如从本地库查询客户数据、将文件写入本地存储),完全不需要感知OCR服务的存在,也不需要引入任何OCR相关的依赖
- 跨能力场景的逻辑编排全部上移:
- 涉及同时用到OCR数据和本地存储能力的业务流程(比如OCR识别后入库、本地文件上传OCR识别等),全部在
Facade层或者对应领域服务中编排:举个例子,做OCR识别入库流程时,由Facade层分别调用OCR适配器实现的文件数据接口拿原始图像、调用OCR适配器实现的客户数据接口拿识别结果、再调用两个本地适配器的持久化接口把数据写入本地库即可,整个链路中适配器之间没有任何直接依赖。
- 涉及同时用到OCR数据和本地存储能力的业务流程(比如OCR识别后入库、本地文件上传OCR识别等),全部在
常见误区澄清
生产环境中一个适配器实现多个端口、一个端口有多个不同适配器实现(比如客户数据端口同时存在本地数据库实现、OCR实现、第三方CRM实现)是非常普遍的场景,完全不违反六边形架构的原则。不要被教程里的极简示例误导,只要严格守住“适配器不互相直接调用、编排逻辑不沉到适配器层、端口定义归领域层”的边界,就不会出现架构腐化、依赖混乱的问题。
内容的提问来源于stack exchange,提问作者Jose Climent
相关产品推荐
相关产品推荐

