src/main/java
├── com.example
│ ├── common # 通用工具类、基础异常、常量
│ ├── order # 订单限界上下文(模块示例)
│ │ ├── interfaces # 用户接口层
│ │ │ ├── controller # HTTP/REST API
│ │ │ ├── rpc # Dubbo/gRPC 接口
│ │ │ └── consumer # 消息队列消费者(如Kafka监听)
│ │ ├── application # 应用层
│ │ │ ├── service # 应用服务(流程编排)
│ │ │ ├── dto # 入参/出参对象(适配外部协议)
│ │ │ └── event # 应用事件(如发送邮件通知)
│ │ ├── domain # 领域层(核心业务逻辑)
│ │ │ ├── model # 领域模型
│ │ │ │ ├── aggregate # 聚合根(如Order)
│ │ │ │ ├── entity # 实体(如OrderItem)
│ │ │ │ └── vo # 值对象(如Address)
│ │ │ ├── service # 领域服务(跨聚合逻辑)
│ │ │ ├── event # 领域事件(如OrderPaidEvent)
│ │ │ ├── repository # 仓储接口(抽象定义)
│ │ │ └── spec # 规约模式(动态查询条件)
│ │ └── infrastructure # 基础设施层
│ │ ├── persistence # 持久化实现
│ │ │ ├── entity # 数据库实体(JPA/MyBatis)
│ │ │ ├── converter # 领域对象与持久化对象转换器
│ │ │ └── repository # 仓储实现(如OrderRepositoryImpl)
│ │ ├── client # 外部服务调用(支付、库存)
│ │ └── mq # 消息队列生产者
│ └── user # 用户限界上下文(其他模块)
└── resources
├── config # 配置文件
└── scripts # 数据库脚本
分层 | 职责 | 技术选型 | 关键输出 |
---|---|---|---|
用户接口层 | 处理 HTTP/RPC/消息,参数校验,DTO 转换 | Spring MVC、Dubbo、Kafka | Controller、DTO、消息监听类 |
应用层 | 事务管理、权限校验、领域逻辑编排 | Spring Transaction、AspectJ | 应用服务类、应用事件 |
领域层 | 实现核心业务规则,定义聚合根、实体 | 纯 Java(无框架依赖) | 聚合根、领域事件、领域服务 |
基础设施层 | 数据库访问、消息发送、外部服务调用 | JPA、MyBatis、Redis、Kafka | 仓储实现、防腐层、消息生产者 |
@RestController
@RequestMapping("/orders")
public class OrderController {
@Autowired
private OrderAppService appService;
@PostMapping
public OrderResponse createOrder(@RequestBody OrderRequest request) {
// 参数校验(如商品ID合法性)
ValidateUtils.checkValid(request);
// 调用应用层服务
return appService.createOrder(request);
}
}
@Service
public class OrderAppService {
@Autowired
private OrderRepository orderRepository;
@Autowired
private DomainEventPublisher eventPublisher;
@Transactional
public OrderResponse createOrder(OrderRequest request) {
// 1. 调用领域层创建聚合根
Order order = OrderFactory.create(request);
// 2. 持久化聚合根
orderRepository.save(order);
// 3. 发布领域事件(如触发库存扣减)
eventPublisher.publish(new OrderCreatedEvent(order.getId()));
// 4. 返回响应
return OrderConverter.toResponse(order);
}
}
职责:
示例:
// 聚合根(封装核心业务逻辑)
public class Order implements AggregateRoot<Long> {
private Long id;
private OrderStatus status;
private List<OrderItem> items;
// 业务方法:支付订单
public void pay(Payment payment) {
if (status != OrderStatus.CREATED) {
throw new IllegalOrderStateException("Order must be created");
}
if (!payment.validate()) {
throw new PaymentFailedException("Invalid payment");
}
status = OrderStatus.PAID;
registerEvent(new OrderPaidEvent(id)); // 记录领域事件
}
}
落地难点:
归属对象:聚合根(Aggregate Root)、实体(Entity)、值对象(Value Object)。
设计原则:
@Entity
)。示例代码:
// 领域实体(属于聚合根的一部分)
public class OrderItem {
private ProductId productId; // 值对象
private Integer quantity;
private Money price; // 值对象(金额+货币单位)
// 业务逻辑:计算商品总价
public Money calculateTotal() {
return price.multiply(quantity);
}
}
// 聚合根(订单的核心管理边界)
public class OrderAggregate implements AggregateRoot<OrderId> {
private OrderId id;
private OrderStatus status;
private List<OrderItem> items;
private Address address; // 值对象
// 核心业务逻辑:支付订单
public void pay(Payment payment) {
if (status != OrderStatus.CREATED) {
throw new IllegalOrderStateException("Only created orders can be paid");
}
this.status = OrderStatus.PAID;
registerEvent(new OrderPaidEvent(this.id, payment)); // 记录领域事件
}
}
职责:
示例:
// 仓储实现(数据库操作)
@Repository
public class OrderRepositoryImpl implements OrderRepository {
@Autowired
private OrderJpaRepository jpaRepository;
@Override
public Order findById(Long id) {
OrderEntity entity = jpaRepository.findById(id).orElseThrow();
return OrderConverter.toDomain(entity); // 转换领域对象
}
}
// 防腐层(隔离第三方支付接口)
@Component
public class PaymentClient {
public PaymentResult pay(OrderPaymentCommand command) {
ThirdPartyResponse response = callThirdParty(command);
return PaymentConverter.toResult(response); // 转换领域模型
}
}
落地难点:
归属对象:数据库实体(与 ORM 框架绑定的对象)、DAO 实现。
设计原则:
Converter
类实现领域对象与数据库实体的双向转换。示例代码:
// 数据库实体(JPA 注解)
@Entity
@Table(name = "orders")
public class OrderEntity {
@Id
private Long id;
private String status;
@Column(name = "address_json")
private String addressJson; // 值对象序列化为 JSON
}
// 转换器(领域对象 ↔ 数据库实体)
public class OrderConverter {
public static OrderAggregate toDomain(OrderEntity entity) {
Address address = JsonUtils.fromJson(entity.getAddressJson(), Address.class);
return OrderAggregate.builder()
.id(new OrderId(entity.getId()))
.status(OrderStatus.valueOf(entity.getStatus()))
.address(address)
.build();
}
public static OrderEntity toEntity(OrderAggregate order) {
OrderEntity entity = new OrderEntity();
entity.setId(order.getId().getValue());
entity.setStatus(order.getStatus().name());
entity.setAddressJson(JsonUtils.toJson(order.getAddress()));
return entity;
}
}
防腐层设计
infrastructure/client
中隔离外部服务依赖:// 基础设施层:调用支付服务(防止领域层污染)
@Component
public class PaymentClient {
@Autowired
private ThirdPartyPaymentService paymentService;
// 将第三方返回结果转换为领域对象
public PaymentResult pay(OrderPaymentCommand command) {
ThirdPartyResponse response = paymentService.invoke(command);
return PaymentResultConverter.fromResponse(response);
}
}
对象类型 | 所属分层 | 职责 | 技术依赖 |
---|---|---|---|
领域实体 | 领域层(domain) | 封装业务逻辑和状态变更 | 无框架依赖 |
值对象 | 领域层(domain) | 描述不可变属性(如地址、金额) | 无框架依赖 |
数据库实体 | 基础设施层(infra) | 映射数据库表结构 | 依赖 JPA/MyBatis 等 |
DTO | 应用层(application) | 传输数据,适配外部接口 | 可包含 Jackson 注解 |
OrderAggregate
包含业务方法 pay()
。OrderEntity
只包含 JPA 注解和表结构映射。// 值对象(领域层)
public class Address {
private String province;
private String city;
private String detail;
}
// 数据库实体(基础设施层)
@Entity
public class OrderEntity {
@Column(name = "address_json")
private String addressJson; // 存储为 JSON 字符串
}
public class OrderAggregate {
private List<OrderItem> items = new ArrayList<>();
// 外部必须通过聚合根方法操作 items
public void addItem(ProductId productId, int quantity) {
items.add(new OrderItem(productId, quantity));
}
}
问题 | 解决方案 |
---|---|
聚合根过大导致性能问题 | 拆分聚合 + CQRS 分离读写模型 |
领域事件丢失或重复消费 | 消息队列事务 + 消费者幂等设计 |
复杂查询性能低下 | 单独构建读模型(Elasticsearch 物化视图) |
DDD 分层架构通过明确的职责划分,将业务复杂度与技术复杂度解耦。其核心价值在于:
实际落地中需注意:避免过度设计(简单 CRUD 系统无需 DDD),接受阶段性不完美,并通过自动化测试和代码规范保障架构一致性。
// ❌ 错误做法:领域模型被 JPA 污染
@Entity
public class Order {
@Id
private Long id;
@Column(name = "status")
private String status; // 直接暴露数据库字段
// 业务逻辑混杂在数据对象中
public void pay() { ... }
}
// ✅ 正确做法:领域模型与数据库实体分离
// 领域层(无框架依赖)
public class Order {
private OrderId id;
private OrderStatus status;
public void pay() { ... } // 纯业务逻辑
}
// 基础设施层(数据库实体)
@Entity
@Table(name = "orders")
public class OrderEntity {
@Id
private Long id;
private String status; // 数据库字段名可自由定义
}
// 领域层:值对象
public class Address {
private String province;
private String city;
private String detail;
}
// 基础设施层:数据库实体
@Entity
public class OrderEntity {
@Column(name = "address_json")
private String addressJson; // 存储为 JSON 字符串
}
// 转换器:领域对象 ↔ 数据库实体
public class OrderConverter {
public static Address toAddress(String json) {
return JsonUtils.fromJson(json, Address.class);
}
}
-- 数据库表设计
CREATE TABLE orders (
id BIGINT PRIMARY KEY,
province VARCHAR(50),
city VARCHAR(50),
address_detail VARCHAR(100)
);
public class Order implements AggregateRoot<Long> {
private List<OrderItem> items = new ArrayList<>();
// 外部必须通过聚合根添加商品
public void addItem(ProductId productId, int quantity) {
if (this.status != OrderStatus.DRAFT) {
throw new IllegalOrderStateException("Cannot modify order");
}
items.add(new OrderItem(productId, quantity));
}
// 禁止直接暴露 items 集合
public List<OrderItem> getItems() {
return Collections.unmodifiableList(items);
}
}
DDD 分层架构的核心目标是通过职责分离和统一语言,让业务逻辑与技术实现解耦。其难点不在于技术,而在于团队能否:
最终,DDD 的成败取决于团队是否愿意让代码反映业务,而非让业务适应代码。