六边形架构(DDD)完整落地实战:从理论到可运行代码

六边形架构(DDD)完整落地实战:从理论到可运行代码 在传统分层架构Controller → Service → DAO中业务代码常常被接口、第三方调用、数据库、消息中间件等外部技术细节裹挟。一旦数据源、对接渠道、外部系统发生变更核心业务就要大面积改代码测试困难、迭代风险高。什么是六边形架构六边形架构Hexagonal Architecture也叫端口与适配器架构是 DDD 领域驱动设计最经典的落地架构之一。本文实现可落地、可用于生产的六边形架构以订单创建场景作为案例语言通俗、代码完整适配 Java/SpringBoot 主流技术栈。一、实战场景说明实现一个极简但完整的业务用户创建订单 → 校验订单 → 保存订单 → 发送通知严格遵守六边形架构规则领域层完全纯净不依赖任何框架、DB、第三方接口依赖方向永远向内外层依赖内层端口 接口适配器 实现业务与技术彻底隔离二、项目包结构六边形标准结构Plain Textcom.order├── domain/ # 内核领域层纯业务无任何外部依赖│ ├── entity/ # 领域实体│ └── service/ # 领域服务核心业务规则├── application/ # 内核应用层流程编排│ └── service/ # 应用服务├── port/ # 端口抽象接口业务定义能力│ ├── inbound/ # 入站端口外部调用系统│ └── outbound/ # 出站端口系统调用外部├── adapter/ # 适配器具体实现技术细节│ ├── inbound/ # 入站适配器Controller、RPC、Job│ └── outbound/ # 出站适配器DB、Redis、第三方接口└── OrderApplication.java # 启动类一句话看懂domain application 系统心脏port 插座抽象adapter 插头实现三、代码实现完整可复制1. 领域层最内层纯业务零依赖1.1 领域实体Order.javajavapackage com.order.domain.entity;import lombok.Data;import java.math.BigDecimal;import java.time.LocalDateTime;/*** 领域实体只包含业务属性与业务行为* 无任何框架注解、无DB注解、无第三方依赖*/Datapublic class Order {private String orderId;private String userId;private BigDecimal amount;private LocalDateTime createTime;// 领域行为订单创建规则public void create() {if (amount null || amount.compareTo(BigDecimal.ZERO) 0) {throw new RuntimeException(订单金额必须大于0);}this.createTime LocalDateTime.now();}}1.2 领域服务OrderDomainService.javajavapackage com.order.domain.service;import com.order.domain.entity.Order;import org.springframework.stereotype.Service;/*** 领域服务处理跨实体的核心业务规则* 纯业务逻辑不处理技术、不操作DB*/Servicepublic class OrderDomainService {public void createOrder(Order order) {// 执行业务行为order.create();// 可继续添加库存校验、价格计算、风控规则等纯业务逻辑}}2. 端口层抽象接口定义能力不做实现2.1 入站端口给外部调用javapackage com.order.port.inbound;import com.order.domain.entity.Order;public interface CreateOrderUseCase {Order createOrder(Order order);}2.2 出站端口定义需要外部能力DB、消息等javapackage com.order.port.outbound;import com.order.domain.entity.Order;// 订单仓储端口抽象public interface OrderRepositoryPort {Order save(Order order);}javapackage com.order.port.outbound;// 通知端口抽象public interface NotifyPort {void sendNotify(String orderId);}3. 应用层流程编排不写业务规则javapackage com.order.application.service;import com.order.domain.entity.Order;import com.order.domain.service.OrderDomainService;import com.order.port.inbound.CreateOrderUseCase;import com.order.port.outbound.NotifyPort;import com.order.port.outbound.OrderRepositoryPort;import lombok.RequiredArgsConstructor;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;/*** 应用服务只做流程编排不写核心业务规则* 依赖领域服务 出站端口抽象接口*/ServiceRequiredArgsConstructorpublic class OrderApplicationService implements CreateOrderUseCase {private final OrderDomainService orderDomainService;private final OrderRepositoryPort orderRepositoryPort;private final NotifyPort notifyPort;OverrideTransactional(rollbackFor Exception.class)public Order createOrder(Order order) {// 1. 领域层执行业务规则orderDomainService.createOrder(order);// 2. 调用出站端口保存订单具体实现由适配器完成Order savedOrder orderRepositoryPort.save(order);// 3. 调用出站端口发送通知notifyPort.sendNotify(savedOrder.getOrderId());return savedOrder;}}4. 适配器层技术实现全部放在外层4.1 入站适配器HTTP 接口Controllerjavapackage com.order.adapter.inbound;import com.order.domain.entity.Order;import com.order.port.inbound.CreateOrderUseCase;import lombok.RequiredArgsConstructor;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;RestControllerRequestMapping(/order)RequiredArgsConstructorpublic classOrderController {private final CreateOrderUseCase createOrderUseCase;PostMapping(/create)public ResponseEntityOrder createOrder(RequestBody Order order) {return ResponseEntity.ok(createOrderUseCase.createOrder(order));}}4.2 出站适配器DB 实现MySQLjavapackage com.order.adapter.outbound;import com.order.domain.entity.Order;import com.order.port.outbound.OrderRepositoryPort;import com.order.infra.mapper.OrderMapper;import com.order.infra.po.OrderPO;import lombok.RequiredArgsConstructor;import org.springframework.stereotype.Component;/*** DB 适配器实现端口接口* 领域层完全不知道DB是什么*/ComponentRequiredArgsConstructorpublic class OrderRepositoryAdapter implements OrderRepositoryPort {private final OrderMapper orderMapper;Overridepublic Order save(Order order) {// 领域实体 → 持久化对象OrderPO orderPO convert(order);orderMapper.insert(orderPO);return order;}private OrderPO convert(Order order) {// 省略转换逻辑OrderPO po new OrderPO();po.setOrderId(order.getOrderId());po.setUserId(order.getUserId());po.setAmount(order.getAmount());return po;}}4.3 出站适配器通知实现javapackage com.order.adapter.outbound;import com.order.port.outbound.NotifyPort;import lombok.RequiredArgsConstructor;import org.springframework.stereotype.Component;/*** 通知适配器可随时替换为短信、邮件、MQ* 领域/应用层完全无感*/ComponentRequiredArgsConstructorpublic class NotifyAdapter implements NotifyPort {Overridepublic void sendNotify(String orderId) {System.out.println(【适配器】发送订单通知 orderId);}}四、核心亮点六边形架构威力体现场景 1切换数据库你只需要新增一个适配器OrderRepositoryMongoAdapter领域层、应用层一行代码都不用改场景 2切换通知方式短信 → 微信 → MQ只需要修改NotifyAdapter业务内核完全不动场景 3单元测试极简单javaMockBeanprivate OrderRepositoryPort orderRepositoryPort;MockBeanprivate NotifyPort notifyPort;不用启动 DB、MQ、Redis直接测试业务逻辑。五、架构合规性检查✅ 领域层无任何外部依赖✅ 应用层只依赖领域与端口✅ 适配器全部在最外层✅ 依赖方向永远向内✅ 业务与技术完全解耦这就是标准六边形架构 DDD 落地形态。六、总结六边形架构不是炫技它真正解决的是业务代码不被技术污染系统永远可扩展、可替换、可测试。在实战中只要记住三句话领域层写业务不碰任何技术端口是抽象适配器是实现所有依赖必须向内绝不外翻这套代码可以直接用于电商、支付、SAAS、微服务项目。