# Spring Boot + DDD 实战架构

URL: https://caijiao.org/ddd/chapter4/spring-ddd
Source: docs/ddd/chapter4/spring-ddd.md
Description: 介绍如何在 Spring Boot 项目中实现领域驱动设计（DDD）架构，结合 DDD 理念与 Spring Boot 框架的最佳实践。

在实际开发中，Spring Boot 是一个非常受欢迎的框架，适用于构建企业级应用程序。而领域驱动设计（DDD）则是帮助我们理解复杂业务问题并进行建模的一种方法。在 Spring Boot 项目中结合 DDD，可以帮助我们设计出清晰、高内聚、低耦合的系统架构。

本文将展示如何在 Spring Boot 项目中应用 DDD 实战架构，介绍项目的层次划分、命名规范、模块化策略以及如何将 DDD 的各个概念有效地结合到项目中。

## 1. 项目结构划分与命名规范

在使用 DDD 时，我们通常会按**领域**来组织代码，而不是按技术层次（如控制器、服务等）。下面是一个典型的 Spring Boot 项目结构，它遵循 DDD 架构并结合了 Spring Boot 的约定：

```
src
├── main
│   ├── java
│   │   ├── com
│   │   │   ├── example
│   │   │   │   ├── application
│   │   │   │   │   └── service
│   │   │   │   ├── domain
│   │   │   │   │   ├── model
│   │   │   │   │   └── service
│   │   │   │   ├── infrastructure
│   │   │   │   │   ├── repository
│   │   │   │   │   └── messaging
│   │   │   │   ├── interface
│   │   │   │   │   ├── controller
│   │   │   │   │   └── dto
└── resources
    └── application.properties
```

### 1.1. 目录结构说明

- **application**：应用层，负责处理用户请求并协调领域层的业务逻辑。
- **domain**：领域层，包含领域模型（实体、值对象、聚合根等）和领域服务。该层是核心层，包含了系统的业务逻辑。
- **infrastructure**：基础设施层，包含与外部世界的交互（如数据库、消息队列、外部 API 等）。
- **interface**：接口层，包含与外部世界的交互接口，如 REST API 控制器、DTO（数据传输对象）等。

### 1.2. 命名规范

- **实体（Entity）**：命名为 `DomainNameEntity`，例如 `OrderEntity`、`CustomerEntity`。
- **值对象（Value Object）**：命名为 `DomainNameVO`，例如 `MoneyVO`、`AddressVO`。
- **聚合根（Aggregate Root）**：命名为 `DomainNameAggregate`，例如 `OrderAggregate`、`CustomerAggregate`。
- **领域服务（Domain Service）**：命名为 `DomainNameService`，例如 `OrderService`、`PaymentService`。
- **应用服务（Application Service）**：命名为 `DomainNameApplicationService`，例如 `OrderApplicationService`。

## 2. 模块化策略

在 Spring Boot 项目中，我们可以采用模块化的方式来组织代码。通常，项目会根据功能模块进行拆分，每个模块中包含其相关的领域、应用、基础设施等内容。Spring Boot 提供了非常便利的支持，可以通过 Maven 多模块来实现模块化。

例如，以下是一个多模块的示例：

```
pom.xml (Parent Module)
├── order-service (Order Module)
│   ├── pom.xml
│   ├── src/main/java/com/example/order
│   └── resources/application.properties
├── customer-service (Customer Module)
│   ├── pom.xml
│   ├── src/main/java/com/example/customer
│   └── resources/application.properties
```

每个子模块内部可以按照 DDD 架构进行设计，确保每个模块独立发展，减少模块之间的依赖关系。模块化结构还能支持不同团队并行开发，并保持高内聚低耦合。

## 3. 分层架构设计

在 Spring Boot 项目中实现 DDD 时，可以采用经典的分层架构，通常包含以下几层：

- **领域层（Domain Layer）**：该层包含业务逻辑，模型对象（实体、值对象）和领域服务，完全独立于技术细节。
- **应用层（Application Layer）**：该层负责协调领域对象的操作，接收来自用户的请求，调用领域服务，返回处理结果。它不包含任何业务逻辑，只是业务逻辑的协调者。
- **基础设施层（Infrastructure Layer）**：该层负责与外部系统的交互，如数据库操作、消息队列的处理等。它可以使用 Spring Data JPA 或 MyBatis 来进行数据库持久化。
- **接口层（Interface Layer）**：该层负责处理与用户或外部系统的交互，如控制器、REST API 等。

### 3.1. 领域层示例

领域层包含实体、值对象、聚合根和领域服务。例如，以下是一个订单（Order）聚合的实现：

```java
// Order Entity
public class Order {
    private Long id;
    private Customer customer;
    private List<OrderItem> items;

    // 省略构造方法、getter、setter

    public void addItem(OrderItem item) {
        items.add(item);
    }
}

// OrderItem Entity
public class OrderItem {
    private Long id;
    private Product product;
    private int quantity;

    // 省略构造方法、getter、setter
}
```

### 3.2. 应用层示例

应用层会调用领域服务执行操作，如下所示：

```java
@Service
public class OrderApplicationService {

    private final OrderService orderService;

    @Autowired
    public OrderApplicationService(OrderService orderService) {
        this.orderService = orderService;
    }

    public void createOrder(OrderDTO orderDTO) {
        Order order = new Order(orderDTO.getCustomer(), orderDTO.getItems());
        orderService.createOrder(order);
    }
}
```

### 3.3. 基础设施层示例

基础设施层包含与数据库的交互，如 Spring Data JPA 的 Repository：

```java
@Repository
public interface OrderRepository extends JpaRepository<Order, Long> {
    List<Order> findByCustomerId(Long customerId);
}
```

### 3.4. 接口层示例

接口层负责暴露 REST API 接口，与用户交互：

```java
@RestController
@RequestMapping("/orders")
public class OrderController {

    private final OrderApplicationService orderApplicationService;

    @Autowired
    public OrderController(OrderApplicationService orderApplicationService) {
        this.orderApplicationService = orderApplicationService;
    }

    @PostMapping
    public ResponseEntity<Void> createOrder(@RequestBody OrderDTO orderDTO) {
        orderApplicationService.createOrder(orderDTO);
        return ResponseEntity.ok().build();
    }
}
```

## 4. Spring Boot + DDD 整合实践

将 DDD 的理念应用到 Spring Boot 项目中时，我们要特别注意以下几点：

- **高内聚，低耦合**：每个层次、每个模块都要保持清晰的职责分离，不应该让某个层次或模块承担过多的责任。
- **领域模型的定义**：确保领域模型的设计能准确表达业务需求，聚焦核心业务问题。
- **持久化与业务逻辑分离**：保持业务逻辑与数据持久化操作分离，尽量避免将业务逻辑耦合到数据库操作中。

## 5. 总结

在 Spring Boot 项目中结合 DDD，能够帮助开发者更好地理解和设计复杂的业务需求，增强系统的可维护性和可扩展性。通过合理的分层设计、模块化策略以及清晰的命名规范，能够确保系统的稳定性和灵活性。在实际应用中，Spring Boot 提供的丰富生态支持，使得 DDD 架构的实施更加顺利与高效。
