
Ddd Architecture Cola
- 13 installs
- 1 repo stars
- Updated July 29, 2026
- full-statck-skills/ddd-skills
Scaffolds and validates Alibaba COLA v5 architecture with adapter/application/domain/infrastructure layers, ArchUnit dependency checks, and CQRS.
About
Guides COLA v5 project scaffolding and architecture validation, combining a creator and validator with ArchUnit dependency-rule checking and CQRS integration. A developer uses it to build or audit Alibaba COLA-framework DDD projects.
- Multi-module Maven/Gradle scaffolding
- ArchUnit compliance scoring with fix suggestions
Ddd Architecture Cola by the numbers
- 13 all-time installs (skills.sh)
- Ranked #3,516 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Jul 30, 2026 (Skillselion catalog sync)
npx skills add https://github.com/full-statck-skills/ddd-skills --skill ddd-architecture-colaAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 13 |
|---|---|
| repo stars | ★ 1 |
| Last updated | July 29, 2026 |
| Repository | full-statck-skills/ddd-skills ↗ |
What it does
Scaffolds and validates Alibaba COLA v5 architecture with adapter/application/domain/infrastructure layers, ArchUnit dependency checks, and CQRS.
Files
DDD Architecture — COLA v5(菱形架构)
COLA v5 是阿里巴巴开源的 DDD 架构框架,采用菱形架构——Domain 居中,Adapter 和 Infrastructure 分居两侧。本 Skill 合并 cola-creator(脚手架生成)和 cola-validator(架构校验),提供从创建到持续校验的全流程能力。
Workflow
输入 → 意图识别
├─ "创建 COLA 项目" → Creator 流程(5 步)
│ Step 1: 确认项目名/包名/语言/Spring Boot 版本/CQRS 开关
│ Step 2: 生成多模块 Maven/Gradle 骨架
│ Step 3: 生成基类(AggregateRoot/Entity/VO/DomainEvent)
│ Step 4: 生成 Demo 聚合代码(四层完整链路)
│ Step 5: 生成 ArchUnit 测试 + check_cola.py 脚本
└─ "检查架构合规" → Validator 流程(4 步)
Step 1: 接收项目路径或代码片段
Step 2: 执行 6 项合规检查
Step 3: P0/P1/P2 权重扣分,输出评分报告
Step 4: 输出违规清单 + 修复建议
完成后引导 → ddd-domain-designer / ddd-api-designer / ddd-code-reviewerWhen to Use / Boundary
什么时候该用(适用场景)
- Java + Spring Boot 企业级项目,MyBatis/JPA 技术栈
- 需要脚手架自动生成多模块 COLA 项目
- 需要 ArchUnit 自动校验架构合规
- 国内阿里系技术生态(Dubbo/RocketMQ/Nacos)
- 团队 5-50 人,业务中高复杂度
不适用场景
- 非 Java 项目 → 不适用,推荐
ddd-architecture-clean/ddd-architecture-hexagonal - 非 Spring Boot → 不适用,COLA 强绑定 Spring 生态
- 2-3 人团队简单 CRUD → 不适用,
ddd-architecture-layered更轻量 - 已有整洁/六边形架构正常运行 → 不适用,无需迁移
- 快速原型/PoC 阶段 → 不适用,架构成本过高
菱形架构核心原理
┌──────────────┐
│ Adapter │ ← 适配层:HTTP/MQ/RPC 协议适配与 DTO 转换
└──────┬───────┘
┌──────▼───────┐
│ Application│ ← 应用层:用例编排、事务管理、CQRS 执行器
┌───────┴───────┬───────┴───────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Domain │ │ Domain │ │ Domain │ ← 领域层:业务规则 ★ 零框架依赖
│ ★ │ │ ★ │ │ ★ │
└──────────┘ └──────────┘ └──────────┘
▲ ▲ ▲
└───────────────┴───────────────┘
│
┌──────▼───────┐
│Infrastructure│ ← 基础设施层:DB/MQ/缓存/外部 API 实现
└──────────────┘| 层 | 模块 | 职责 | 依赖 |
|---|---|---|---|
| Adapter | {p}-adapter | REST/RPC/MQ 协议适配、DTO 转换、参数校验 | → app, domain |
| Application | {p}-app | Command/Query 执行器、事务编排、扩展点路由 | → domain, infra |
| Domain | {p}-domain | 聚合/E/VO、领域事件、Repository/Gateway 接口、Ability | 无依赖 |
| Infrastructure | {p}-infrastructure | Repository/Gateway 实现、PO↔DO 转换、配置、组件 | → domain |
v5 新增特性:Extension Point(@ExtensionPoint + @Extension(bizId) 多租户差异化)、Ability(领域能力抽象)、组件化基础设施(分布式锁/限流/熔断)、CQRS 强化(command/query 执行器严格分离)
生成能力:cola-creator
AI 交互确认 → 项目名/包名(com.example.order) / 语言(Java 17+/Kotlin) / Spring Boot(3.2+/3.1) / CQRS(否/L1/L2) / Demo(默认Order)
生成内容:
├── pom.xml/build.gradle(6 模块:start/adapter/app/domain/infrastructure/common)
├── COLA v5 标准目录结构 + 基类(AggregateRoot/Entity/VO/DomainEvent)
├── Demo 聚合(Order 四层完整示例)
├── DDD 中间件配置(DomainEventBus、ExtensionExecutor)
├── ArchUnit 测试 + check_cola.py 脚本
└── .gitignore + README两种方式:mvn archetype:generate -DarchetypeGroupId=com.alibaba.cola -DarchetypeArtifactId=cola-archetype-web -DarchetypeVersion=5.0.0(快速)或手动多模块(生产推荐,详见 references/02)。
校验能力:cola-validator
| 检查项 | 级别 | 说明 | 检测方式 |
|---|---|---|---|
| 依赖方向 | P0 | Domain 不可依赖 Infrastructure/App/Adapter | import 解析 |
| Domain 纯净度 | P0 | Domain 无 Spring/JPA/MyBatis/Hibernate import | import 扫描 |
| 层职责 | P0 | Adapter 无 SQL、App 无业务 if/else | AST 分析 |
| 包命名规范 | P1 | 按 COLA 约定命名 | 正则匹配 |
| 模块循环依赖 | P1 | DFS 检测依赖图 | 图遍历 |
| 聚合设计 | P1 | 聚合>5 实体、跨聚合引用、值对象可变性 | AST 分析 |
评分模型:评分 = 100 - 扣分(P0=10分/项,P1=5分/项,P2=2分/项)。≥90→A,70-89→B,50-69→C,<50→D。
运行:mvn test -Dtest=ArchitectureComplianceTest(ArchUnit Java 测试)或 python scripts/check_cola.py /path/to/project(Python 轻量校验)。
目录结构(COLA v5 多模块)
{project}/
├── start/ — 启动模块:Application.java(@EnableCola), config/
├── adapter/ — 适配器层
│ ├── web/ — controller/dto/advice(GlobalExceptionHandler)
│ ├── rpc/ — Dubbo/gRPC provider/consumer/facade
│ ├── job/ — 定时任务调度
│ └── message/ — MQ consumer/producer
├── app/ — 应用层
│ ├── executor/ — command/query/event/extension 执行器
│ ├── model/ — command/query/event/dto 对象
│ ├── eventhandler/ — 事件处理器
│ └── extension/ — 扩展点(point/biz/impl)
├── domain/ ★ — 领域层(零框架依赖)
│ ├── model/ — entity/vo/aggregate/event/enums
│ ├── service/ — 领域服务
│ ├── ability/ — 领域能力(v5 新概念)
│ ├── gateway/ — 防腐层接口
│ └── repository/ — 仓储接口
├── infrastructure/ — 基础设施层
│ ├── config/ — DB/缓存/MQ/RPC 配置
│ ├── persistence/ — repositoryimpl/mapper/dao/entity(PO)
│ ├── gatewayimpl/ — 网关实现
│ ├── external/ — 外部服务客户端
│ └── component/ — 分布式锁/限流/熔断/重试
└── common/ — 常量/异常/工具/注解/上下文落地步骤
Phase 1 [1天] 脚手架 → Phase 2 [2-3天] 领域建模(配合 ddd-domain-designer)→ Phase 3 [2-3天] 基础设施(Repository/Gateway/PO)→ Phase 4 [1-2天] 应用+适配(Executor → Controller)→ Phase 5 [0.5天] 架构校验 → Phase 6 [持续] CI/CD 自动校验
核心规则(Core Rules)
四大约束(P0):①Domain 零框架依赖(禁止 Spring/JPA/MyBatis)②App 层无业务 if/else ③Adapter 无 SQL/业务判断 ④模块间无循环依赖
依赖方向:adapter → app → domain ← infrastructure(domain 不依赖任何人)
Gotchas — 常见坑(15条)
1. Domain 层放 Controller — Controller 在 Adapter 层。Domain 下出现 @RestController 说明分层全错。 2. App 层直接操作 Mapper — 必须通过 Repository 接口:orderRepository.save(order) 而非 orderMapper.insert()。 3. 模块命名不匹配 COLA — 必须为 {project}-adapter/app/domain/infrastructure,否则 ArchUnit 校验失败。 4. Command/Query 放 Domain 层 — 应放 app/model/command/ 和 app/model/query/。 5. Archetype 版本不匹配 — cola-archetype-web 5.0.0 要求 Spring Boot 3.x,2.x 需手动适配。 6. Domain 层用 JPA @Entity — 持久化映射在 Infrastructure 层用 PO 类。 7. App 层抛框架异常 — 应抛 BizException,Adapter 层统一转换。 8. 跨聚合直接引用对象 — 聚合间通过 ID 引用,不直接 Order.getCustomer()。 9. 值对象带 setter — ValueObject 应不可变(final + 无 setter),修改返回新对象。 10. 缺少领域事件 — 创建订单/支付/取消等关键操作必须发布领域事件。 11. Adapter 层有业务判断 — Controller/Consumer 不应有任何 if-else。 12. God Service 反模式 — Service 超 500 行应按聚合拆分。 13. 扩展点无默认实现 — 每个 ExtensionPoint 需有默认 @Extension。 14. @EnableCola 缺失 — 启动类必须加 @EnableCola 启用的扩展点和事件总线。 15. PO 与 DO 混用 — 持久化对象和领域对象必须分离,用 Converter 转换。
FAQ(15条)
Q1: COLA v5 和整洁架构的关系? COLA v5 是整洁架构的阿里化实现,增加包命名规范、扩展点机制、CQRS 强化和脚手架。
Q2: 为何不用 cola-archetype 直接生成? Archetype 快速但固定,手动搭建更适合生产定制。
Q3: COLA 支持微服务吗? 支持。每个微服务内部按 COLA 四层组织,服务间通过 RPC/MQ 通信。
Q4: CQRS 强制吗? 否。简单场景用 app/service/ 编排,复杂场景切到 CQRS executor。
Q5: check_cola.py 和 ArchUnit 区别? check_cola.py 轻量 import 扫描适合 CI,ArchUnit 强大 AST 分析需 Java 环境。
Q6: Domain 层 @Autowired 怎么处理? Domain 禁止 @Autowired,通过方法参数或构造器注入接口。
Q7: 领域事件送达保证? App 层事务提交后 EventBus.publish(),生产配合 Transactional Outbox 模式。
Q8: COLA 和 Spring Cloud 关系? COLA 是架构规范,Spring Cloud 是基础设施,可完全集成使用。
Q9: 值对象存 JSON 还是拆列? 简单值对象拆列,复杂嵌套存 JSON + Converter 类型转换。
Q10: 聚合太大怎么办? ≤ 5 实体,按业务操作频率拆分。
Q11: 扩展点 bizId 来源? 前端请求头、登录会员等级、租户 ID 路由。
Q12: 无扩展点需求可删吗? 可。app/extension/ 和 domain/ability/ 可不创建。
Q13: common 模块内容? 常量、异常基类、DTO 基类、上下文(UserContext/TenantContext)、自定义注解。
Q14: start 和 adapter 关系? start 启动入口 + 全局配置,adapter 协议适配,start 依赖 adapter。
Q15: 如何确保不泄露敏感配置? 外部化配置 + 环境变量,禁止硬编码密钥,Domain 层不读写配置文件。
Keywords
COLA COLA v5 菱形架构 diamond architecture cola-creator cola-validator ArchUnit CQRS Extension Point 扩展点 Ability 领域能力 Aggregate Root Entity Value Object Domain Event Repository Gateway 防腐层 DDD Spring Boot MyBatis @EnableCola CommandExecutor QueryExecutor
Project Scaffolding
ddd4j Boot 是 COLA v5 架构的 Java 参考实现,基于 Spring Boot 3.5.x,集成 ddd-4-java 和 cqrs-4-java 轻量库,完整实现 DDD、CQRS 和 Event Sourcing 模式。
- 项目生成: 使用
scripts/init_project.py可自动生成 COLA 多模块项目结构,支持单模块单体、多模块单体和微服务三种项目类型,涵盖 pom.xml、package-info.java、.gitignore、mvnw 等必需文件 - 合规验证: 使用
scripts/check_project.py可验证项目的 DDD 分层合规性、依赖方向正确性和包命名规范,输出详细的违规报告和修复建议 - 场景示例: 参考
examples/13-architecture-patterns.md(四种架构模式)、examples/14-single-module.md(单模块单体)、examples/15-multi-module.md(多模块单体)、examples/16-microservices.md(微服务) - 详细说明: 参考
references/14-ddd4j-scaffold.md了解完整的项目生成流程、验证规则、层依赖关系和包命名规范
References
详细参考见 references/ 目录:01-architecture-principles(架构原理)、02-project-scaffold(脚手架)、03-domain-layer(领域层)、04-app-layer(应用层)、05-adapter-layer(适配层)、06-infrastructure(基础设施)、07-archunit-validation(ArchUnit 校验)、08-cqrs-integration(CQRS 集成)
Examples
完整代码见 examples/ 目录:01-quickstart-order(Order 聚合完整实现)、02-customer-crud(CRUD 入门)、03-extension-point(扩展点机制)、04-cqrs-separation(CQRS 分离)、05-archunit-config(ArchUnit 校验 CI/CD 集成)
项目规模示例见 examples/ 目录:06-monolith-simple(单体简单项目)、07-monolith-complex(单体复杂项目)、08-monolith-multi-module(单体多模块项目)、09-microservice-simple-monolith(微服务简单的单体项目)、10-microservice-complex-monolith(微服务复杂的单体项目,基于 ddd4j-gateway)、11-microservice-simple-multi-module(微服务简单的多模块项目,基于 ddd4j-rednote)、12-microservice-complex-multi-module(微服务复杂的多模块项目,基于 ddd4j-pay)
COLA 示例:Order 订单聚合完整实现
本节展示一个完整的订单聚合,涵盖 Domain/App/Adapter/Infrastructure 四层。
领域层 (domain)
// === 聚合根 ===
public class Order extends AggregateRoot<OrderId> {
private OrderId id;
private CustomerId customerId;
private OrderStatus status;
private Money totalAmount;
private List<OrderItem> items;
private LocalDateTime createdAt;
public static Order create(OrderId id, CustomerId customerId, List<OrderItem> items) {
Order order = new Order();
order.id = id;
order.customerId = customerId;
order.status = OrderStatus.DRAFT;
order.items = new ArrayList<>(items);
order.totalAmount = calculateTotal(items);
order.createdAt = LocalDateTime.now();
order.addDomainEvent(new OrderCreatedEvent(id, customerId, order.totalAmount));
return order;
}
public void pay() {
if (!status.canPay()) throw new OrderDomainException("不可支付");
this.status = OrderStatus.PAID;
addDomainEvent(new OrderPaidEvent(this.id, this.totalAmount));
}
public void cancel() {
if (!status.canCancel()) throw new OrderDomainException("不可取消");
this.status = OrderStatus.CANCELLED;
addDomainEvent(new OrderCancelledEvent(this.id));
}
private static Money calculateTotal(List<OrderItem> items) {
return items.stream()
.map(OrderItem::getSubtotal)
.reduce(Money.ZERO, Money::add);
}
// getter 省略
}
// === 值对象 ===
public class OrderId {
private final String value;
public OrderId(String value) {
this.value = Objects.requireNonNull(value);
}
public String getValue() { return value; }
@Override public boolean equals(Object o) { /* 按值比较 */ }
@Override public int hashCode() { return value.hashCode(); }
}
// === 实体 ===
public class OrderItem {
private ProductId productId;
private int quantity;
private Money unitPrice;
public Money getSubtotal() {
return unitPrice.multiply(quantity);
}
}
// === 仓储接口 ===
public interface OrderRepository {
Optional<Order> findById(OrderId id);
Order save(Order order);
Page<Order> findByCustomerId(CustomerId customerId, Pageable pageable);
}应用层 (app)
// === 命令对象 ===
public class OrderCreateCmd {
@NotBlank private String customerId;
@NotEmpty private List<OrderItemDTO> items;
// getter/setter
}
// === 命令执行器 ===
@Component
@CommandExecutor
public class OrderCreateCmdExe implements CommandExecutor<OrderCreateCmd, OrderDTO> {
@Resource private OrderRepository orderRepository;
@Resource private ProductGateway productGateway;
@Override
@Transactional
public OrderDTO execute(OrderCreateCmd cmd) {
// 校验库存
for (OrderItemDTO item : cmd.getItems()) {
InventoryInfo inv = productGateway.checkInventory(
new ProductId(item.getProductId()), item.getQuantity());
if (!inv.isAvailable()) throw new BizException("库存不足: " + item.getProductId());
}
// 创建订单
Order order = Order.create(
new OrderId(UUID.randomUUID().toString()),
new CustomerId(cmd.getCustomerId()),
cmd.getItems().stream().map(this::toItem).collect(Collectors.toList())
);
orderRepository.save(order);
return OrderAssembler.toDTO(order);
}
}
// === 查询执行器 ===
@Component
public class OrderGetQryExe implements QueryExecutor<OrderGetQry, OrderDTO> {
@Resource private OrderRepository orderRepository;
@Override
public OrderDTO execute(OrderGetQry qry) {
return orderRepository.findById(new OrderId(qry.getOrderId()))
.map(OrderAssembler::toDTO)
.orElseThrow(() -> new OrderNotFoundException(qry.getOrderId()));
}
}适配层 (adapter)
@RestController
@RequestMapping("/api/v1/orders")
public class OrderController {
@Resource private OrderCreateCmdExe orderCreateCmdExe;
@Resource private OrderGetQryExe orderGetQryExe;
@PostMapping
public Response<OrderDTO> create(@Valid @RequestBody OrderCreateRequest request) {
return Response.success(orderCreateCmdExe.execute(request.toCommand()));
}
@GetMapping("/{id}")
public Response<OrderDTO> get(@PathVariable String id) {
OrderGetQry qry = new OrderGetQry();
qry.setOrderId(id);
return Response.success(orderGetQryExe.execute(qry));
}
@PostMapping("/{id}/pay")
public Response<Void> pay(@PathVariable String id) {
OrderPayCmd cmd = new OrderPayCmd();
cmd.setOrderId(id);
orderPayCmdExe.execute(cmd);
return Response.success();
}
}基础设施层 (infrastructure)
// === 持久化 PO ===
@Table(name = "t_order")
public class OrderPO {
@Id private String id;
private String customerId;
private String status;
private BigDecimal totalAmount;
private String currency;
private LocalDateTime createdAt;
}
// === MyBatis Mapper ===
@Mapper
public interface OrderMapper {
@Insert("INSERT INTO t_order(id, customer_id, status, total_amount, currency, created_at) " +
"VALUES(#{id}, #{customerId}, #{status}, #{totalAmount}, #{currency}, #{createdAt})")
void insert(OrderPO po);
@Select("SELECT * FROM t_order WHERE id = #{id}")
OrderPO selectById(String id);
}
// === 仓储实现 ===
@Repository
public class OrderRepositoryImpl implements OrderRepository {
@Resource private OrderMapper orderMapper;
@Resource private OrderConverter orderConverter;
@Override
public Order save(Order order) {
OrderPO po = orderConverter.toPO(order);
orderMapper.insert(po);
return orderConverter.toDomain(po);
}
@Override
public Optional<Order> findById(OrderId id) {
return Optional.ofNullable(orderMapper.selectById(id.getValue()))
.map(orderConverter::toDomain);
}
}
// === PO ↔ Domain 转换 ===
@Component
public class OrderConverter {
public OrderPO toPO(Order order) {
OrderPO po = new OrderPO();
po.setId(order.getId().getValue());
po.setStatus(order.getStatus().name());
po.setTotalAmount(order.getTotalAmount().getAmount());
po.setCurrency(order.getTotalAmount().getCurrency().getCurrencyCode());
return po;
}
public Order toDomain(OrderPO po) {
// 注意:领域对象的完整重建需要 items 等关联数据
return Order.builder()
.id(new OrderId(po.getId()))
.status(OrderStatus.valueOf(po.getStatus()))
.totalAmount(new Money(po.getTotalAmount(), Currency.getInstance(po.getCurrency())))
.build();
}
}数据库 DDL
CREATE TABLE t_order (
id VARCHAR(64) PRIMARY KEY,
customer_id VARCHAR(64) NOT NULL,
status VARCHAR(16) NOT NULL DEFAULT 'DRAFT',
total_amount DECIMAL(12,2) NOT NULL,
currency VARCHAR(3) NOT NULL DEFAULT 'CNY',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_customer (customer_id),
INDEX idx_status (status)
);
CREATE TABLE t_order_item (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
order_id VARCHAR(64) NOT NULL,
product_id VARCHAR(64) NOT NULL,
quantity INT NOT NULL,
unit_price DECIMAL(12,2) NOT NULL,
INDEX idx_order (order_id)
);COLA 示例:Customer 客户管理完整实现
展示一个相对简单的单实体聚合的 CRUD 操作,适合初学者理解 COLA 四层交互。
领域层
// === 聚合根 ===
public class Customer extends AggregateRoot<CustomerId> {
private CustomerId id;
private String name;
private Email email;
private PhoneNumber phone;
private CustomerType type;
private CustomerStatus status;
private LocalDateTime createdAt;
public static Customer create(CustomerId id, String name, Email email) {
Customer customer = new Customer();
customer.id = id;
customer.name = name;
customer.email = email;
customer.type = CustomerType.NORMAL;
customer.status = CustomerStatus.ACTIVE;
customer.createdAt = LocalDateTime.now();
customer.addDomainEvent(new CustomerCreatedEvent(id, name, email));
return customer;
}
public void changeEmail(Email newEmail) {
this.email = newEmail;
addDomainEvent(new CustomerEmailChangedEvent(this.id, this.email));
}
public void deactivate() {
if (this.status == CustomerStatus.INACTIVE) return;
this.status = CustomerStatus.INACTIVE;
addDomainEvent(new CustomerDeactivatedEvent(this.id));
}
}
// === 值对象 ===
public final class Email {
private final String value;
private static final Pattern PATTERN = Pattern.compile("^[A-Za-z0-9+_.-]+@(.+)$");
public Email(String value) {
if (value == null || !PATTERN.matcher(value).matches()) {
throw new IllegalArgumentException("Invalid email: " + value);
}
this.value = value;
}
public String getValue() { return value; }
// equals/hashCode 省略
}
// === 仓储接口 ===
public interface CustomerRepository {
Optional<Customer> findById(CustomerId id);
Customer save(Customer customer);
void delete(CustomerId id);
Page<Customer> search(String keyword, Pageable pageable);
}应用层
// === 命令对象 ===
public class CustomerCreateCmd {
@NotBlank private String name;
@Email @NotBlank private String email;
// getter/setter
}
public class CustomerUpdateEmailCmd {
@NotBlank private String customerId;
@Email @NotBlank private String newEmail;
// getter/setter
}
// === 命令执行器 ===
@Component
public class CustomerCreateCmdExe implements CommandExecutor<CustomerCreateCmd, CustomerDTO> {
@Resource private CustomerRepository customerRepository;
@Override
@Transactional
public CustomerDTO execute(CustomerCreateCmd cmd) {
Customer customer = Customer.create(
new CustomerId(UUID.randomUUID().toString()),
cmd.getName(),
new Email(cmd.getEmail())
);
customerRepository.save(customer);
return CustomerAssembler.toDTO(customer);
}
}
// === 查询执行器 ===
@Component
public class CustomerSearchQryExe implements QueryExecutor<CustomerSearchQry, PageResult<CustomerDTO>> {
@Resource private CustomerRepository customerRepository;
@Override
public PageResult<CustomerDTO> execute(CustomerSearchQry qry) {
return customerRepository.search(qry.getKeyword(), qry.toPageable())
.map(CustomerAssembler::toDTO);
}
}适配层
@RestController
@RequestMapping("/api/v1/customers")
public class CustomerController {
@Resource private CustomerCreateCmdExe customerCreateCmdExe;
@Resource private CustomerSearchQryExe customerSearchQryExe;
@PostMapping
public Response<CustomerDTO> create(@Valid @RequestBody CustomerCreateRequest request) {
return Response.success(customerCreateCmdExe.execute(request.toCommand()));
}
@GetMapping
public Response<PageResult<CustomerDTO>> search(
@RequestParam(required = false) String keyword,
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "20") int pageSize) {
CustomerSearchQry qry = new CustomerSearchQry();
qry.setKeyword(keyword);
qry.setPage(page);
qry.setPageSize(pageSize);
return Response.success(customerSearchQryExe.execute(qry));
}
}基础设施层
// 持久化 PO
@Table(name = "t_customer")
public class CustomerPO {
@Id private String id;
private String name;
private String email;
private String phone;
private String type;
private String status;
private LocalDateTime createdAt;
}
// Mapper
@Mapper
public interface CustomerMapper {
@Insert("INSERT INTO t_customer(id, name, email, phone, type, status, created_at) " +
"VALUES(#{id}, #{name}, #{email}, #{phone}, #{type}, #{status}, #{createdAt})")
void insert(CustomerPO po);
@Select("SELECT * FROM t_customer WHERE id = #{id}")
CustomerPO selectById(String id);
@Select("<script>SELECT * FROM t_customer " +
"WHERE 1=1 " +
"<if test='keyword != null'>AND (name LIKE #{keyword} OR email LIKE #{keyword})</if> " +
"ORDER BY created_at DESC</script>")
List<CustomerPO> search(@Param("keyword") String keyword);
}
// 仓储实现
@Repository
public class CustomerRepositoryImpl implements CustomerRepository {
@Resource private CustomerMapper customerMapper;
@Resource private CustomerConverter converter;
@Override
public Customer save(Customer customer) {
CustomerPO po = converter.toPO(customer);
customerMapper.insert(po);
return converter.toDomain(po);
}
@Override
public Optional<Customer> findById(CustomerId id) {
return Optional.ofNullable(customerMapper.selectById(id.getValue()))
.map(converter::toDomain);
}
}数据库 DDL
CREATE TABLE t_customer (
id VARCHAR(64) PRIMARY KEY,
name VARCHAR(128) NOT NULL,
email VARCHAR(256) NOT NULL UNIQUE,
phone VARCHAR(32),
type VARCHAR(16) NOT NULL DEFAULT 'NORMAL',
status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE',
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_email (email),
INDEX idx_status (status)
);COLA 示例:Extension Point 扩展点机制
COLA v5 最核心的新特性。通过扩展点实现业务维度的差异化逻辑。
场景说明
订单价格计算规则,不同会员级别(普通/VIP/企业)有不同的折扣策略。
扩展点定义
// 1. 定义扩展点接口(放在 app/extension/point/)
@ExtensionPoint
public interface OrderPriceCalculateExtPt {
/**
* 计算订单最终价格
* @param order 订单领域对象
* @param basePrice 基础价格
* @return 最终价格
*/
Money calculate(Order order, Money basePrice);
}扩展点实现
// 2. 普通会员 —— 无折扣
@Extension(bizId = "normalOrder")
public class NormalOrderPriceCalculateExt implements OrderPriceCalculateExtPt {
@Override
public Money calculate(Order order, Money basePrice) {
return basePrice; // 原价
}
}
// 3. VIP 会员 —— 9 折
@Extension(bizId = "vipOrder")
public class VipOrderPriceCalculateExt implements OrderPriceCalculateExtPt {
@Override
public Money calculate(Order order, Money basePrice) {
return basePrice.multiply(0.9) // 九折
.setScale(2, RoundingMode.HALF_UP);
}
}
// 4. 企业会员 —— 8 折 + 满减
@Extension(bizId = "enterpriseOrder")
public class EnterpriseOrderPriceCalculateExt implements OrderPriceCalculateExtPt {
@Override
public Money calculate(Order order, Money basePrice) {
Money afterDiscount = basePrice.multiply(0.8); // 八折
if (afterDiscount.compareTo(new Money(10000, Currency.getInstance("CNY"))) >= 0) {
afterDiscount = afterDiscount.subtract(new Money(500, Currency.getInstance("CNY")));
// 满 10000 减 500
}
return afterDiscount.setScale(2, RoundingMode.HALF_UP);
}
}扩展点调用
// 5. 在 App 层注入 ExtensionExecutor
@Component
public class OrderCreateCmdExe implements CommandExecutor<OrderCreateCmd, OrderDTO> {
@Resource
private ExtensionExecutor extensionExecutor;
@Override
@Transactional
public OrderDTO execute(OrderCreateCmd cmd) {
Order order = Order.create(/* ... */);
Money basePrice = order.getTotalAmount();
// 根据业务身份(bizId)自动路由到对应的扩展实现
Money finalPrice = extensionExecutor.execute(
OrderPriceCalculateExtPt.class, // 扩展点接口
cmd.getBizId(), // 业务身份(normal/vip/enterprise)
ext -> ext.calculate(order, basePrice)
);
// 使用 finalPrice 进行后续处理
return OrderAssembler.toDTO(order);
}
}业务身份注入
// 6. 前端请求携带业务身份
@RestController
@RequestMapping("/api/v1/orders")
public class OrderController {
@PostMapping
public Response<OrderDTO> create(
@RequestHeader(value = "X-Biz-Id", defaultValue = "normalOrder") String bizId,
@Valid @RequestBody OrderCreateRequest request) {
request.setBizId(bizId);
return Response.success(orderCreateCmdExe.execute(request.toCommand()));
}
}扩展点最佳实践
| 实践 | 说明 |
|---|---|
| 接口粒度 | 一个扩展点只做一件事,如价格计算、库存校验 |
| 默认实现 | 必须提供默认实现(普通场景),新增扩展不影响已有逻辑 |
| 测试覆盖 | 每个扩展实现都应有独立单元测试 |
| 无状态 | 扩展实现应为无状态,通过参数传递上下文 |
| 日志记录 | 在扩展执行器层记录扩展路由日志,便于排查 |
COLA 示例:CQRS 读写分离完整实现
基于 COLA v5 的 CQRS 强化目录结构,展示命令/查询的严格分离。
写模型(Command Side)
命令对象
// app/model/command/OrderCreateCmd.java
@Data
@Command
public class OrderCreateCmd {
@NotBlank private String customerId;
@NotEmpty private List<OrderItemDTO> items;
private String remark;
private String bizId; // 业务身份(用于扩展点路由)
public void validate() {
Assert.notEmpty(items, "订单项不能为空");
Assert.isTrue(items.size() <= 50, "单笔订单最多 50 项");
}
}命令执行器
// app/executor/command/order/OrderCreateCmdExe.java
@Component
@CommandExecutor
public class OrderCreateCmdExe implements CommandExecutor<OrderCreateCmd, OrderDTO> {
@Resource private OrderRepository orderRepository;
@Resource private ProductGateway productGateway;
@Resource private IdGenerator idGenerator;
@Resource private ExtensionExecutor extensionExecutor;
@Override
@Transactional(rollbackFor = Exception.class)
public OrderDTO execute(OrderCreateCmd cmd) {
cmd.validate();
// 1. 校验库存
for (OrderItemDTO item : cmd.getItems()) {
InventoryInfo inv = productGateway.checkInventory(
new ProductId(item.getProductId()), item.getQuantity());
if (!inv.isAvailable()) {
throw new BizException("库存不足: " + item.getProductId());
}
}
// 2. 创建订单(领域逻辑)
Order order = Order.create(
new OrderId(idGenerator.nextId()),
new CustomerId(cmd.getCustomerId()),
cmd.getItems().stream().map(this::toItem).collect(Collectors.toList())
);
// 3. 应用扩展点(价格计算等)
Money finalPrice = extensionExecutor.execute(
OrderPriceCalculateExtPt.class, cmd.getBizId(),
ext -> ext.calculate(order, order.getTotalAmount())
);
// 4. 保存订单
orderRepository.save(order);
// 5. 发布领域事件(异步处理后续逻辑)
order.getDomainEvents().forEach(eventBus::publish);
return OrderAssembler.toDTO(order);
}
private OrderItem toItem(OrderItemDTO dto) {
return new OrderItem(
new ProductId(dto.getProductId()),
dto.getQuantity(),
new Money(dto.getUnitPrice(), Currency.getInstance("CNY"))
);
}
}读模型(Query Side)
查询对象
// app/model/query/OrderListQry.java
@Data
public class OrderListQry {
private String customerId;
private String status;
private LocalDateTime startTime;
private LocalDateTime endTime;
private int page = 1;
private int pageSize = 20;
public Pageable toPageable() {
return PageRequest.of(page - 1, pageSize, Sort.by("createdAt").descending());
}
public void validate() {
Assert.isTrue(page >= 1, "页码从 1 开始");
Assert.isTrue(pageSize <= 100, "每页最多 100 条");
}
}查询执行器
// app/executor/query/order/OrderListQryExe.java
@Component
public class OrderListQryExe implements QueryExecutor<OrderListQry, PageResult<OrderDTO>> {
@Resource
private OrderRepository orderRepository;
@Override
public PageResult<OrderDTO> execute(OrderListQry qry) {
qry.validate();
// 查询通过 Repository 接口(非事务)
Page<Order> orders = orderRepository.search(qry.toCriteria(), qry.toPageable());
return PageResult.of(
orders.getContent().stream()
.map(OrderAssembler::toDTO)
.collect(Collectors.toList()),
orders.getTotalElements(),
qry.getPage(),
qry.getPageSize()
);
}
}适配层 API
@RestController
@RequestMapping("/api/v1/orders")
public class OrderController {
@Resource private OrderCreateCmdExe orderCreateCmdExe; // Command Executor
@Resource private OrderListQryExe orderListQryExe; // Query Executor
// 命令 API(写操作)
@PostMapping
public Response<OrderDTO> create(@Valid @RequestBody OrderCreateRequest request) {
return Response.success(orderCreateCmdExe.execute(request.toCommand()));
}
// 查询 API(读操作)
@GetMapping
public Response<PageResult<OrderDTO>> list(OrderListQry qry) {
return Response.success(orderListQryExe.execute(qry));
}
@GetMapping("/{id}")
public Response<OrderDTO> get(@PathVariable String id) {
OrderGetQry qry = new OrderGetQry();
qry.setOrderId(id);
return Response.success(orderGetQryExe.execute(qry));
}
}命令 vs 查询 API 设计对比
| 维度 | 命令 API(写) | 查询 API(读) |
|---|---|---|
| HTTP 方法 | POST, PUT, DELETE | GET |
| 请求体 | Command 对象(业务语义) | Query 参数(过滤条件) |
| 返回值 | 有限字段(操作结果 + ID) | 完整数据(DTO) |
| 幂等 | 必须支持 | 天然幂等 |
| 事务 | 需要 | 不需要 |
| 扩展点 | 经常使用 | 基本不用 |
| 限流 | 严格限流 | 宽松限流 |
| 缓存 | 不适用(写入后失效) | 适用 |
事件驱动同步(L2 数据库分离)
// 当需要使用领域事件同步读写模型时
@Component
public class OrderPaidEventExe implements EventExecutor<OrderPaidEvent> {
@Resource private OrderReadModelRepository readModelRepository;
@Override
public void execute(OrderPaidEvent event) {
// 更新读模型(从库/ES)
OrderReadModel readModel = readModelRepository.findById(event.getOrderId());
readModel.setStatus("PAID");
readModel.setPaidAt(LocalDateTime.now());
readModelRepository.save(readModel);
}
}Example 5: ArchUnit 校验完整配置 + CI/CD 流水线集成
本示例展示如何在 COLA v5 项目中配置 ArchUnit 架构合规测试,并将其集成到 GitHub Actions / GitLab CI 流水线中。
目录结构
project-root/
├── start/
├── adapter/
├── app/
├── domain/
├── infrastructure/
├── common/
└── start/src/test/java/com/yourcompany/
└── ArchitectureComplianceTest.java ← 架构校验测试类ArchUnit 校验测试
package com.yourcompany;
import com.tngtech.archunit.junit.AnalyzeClasses;
import com.tngtech.archunit.junit.ArchTest;
import com.tngtech.archunit.lang.ArchRule;
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.*;
@AnalyzeClasses(packages = "com.yourcompany")
public class ArchitectureComplianceTest {
// ── P0: Domain 层零依赖 ──
@ArchTest
static final ArchRule domain_not_depend_infrastructure =
noClasses()
.that().resideInAPackage("..domain..")
.should().dependOnClassesThat()
.resideInAPackage("..infrastructure..")
.because("Domain 层不能依赖 Infrastructure");
@ArchTest
static final ArchRule domain_not_depend_app =
noClasses()
.that().resideInAPackage("..domain..")
.should().dependOnClassesThat()
.resideInAPackage("..app..")
.because("Domain 层不能依赖 App");
@ArchTest
static final ArchRule domain_not_depend_adapter =
noClasses()
.that().resideInAPackage("..domain..")
.should().dependOnClassesThat()
.resideInAPackage("..adapter..")
.because("Domain 层不能依赖 Adapter");
// ── P0: Domain 无框架依赖 ──
@ArchTest
static final ArchRule domain_no_spring =
noClasses()
.that().resideInAPackage("..domain..")
.should().dependOnClassesThat()
.resideInAnyPackage("org.springframework..", "org.springframework.stereotype..")
.because("Domain 层禁止 Spring 依赖");
@ArchTest
static final ArchRule domain_no_jpa =
noClasses()
.that().resideInAPackage("..domain..")
.should().dependOnClassesThat()
.resideInAnyPackage("javax.persistence..", "jakarta.persistence..")
.because("Domain 层禁止 JPA 依赖");
@ArchTest
static final ArchRule domain_no_mybatis =
noClasses()
.that().resideInAPackage("..domain..")
.should().dependOnClassesThat()
.resideInAnyPackage("org.apache.ibatis..")
.because("Domain 层禁止 MyBatis 依赖");
// ── P0: Adapter 层不应访问 Infrastructure ──
@ArchTest
static final ArchRule adapter_not_depend_infrastructure =
noClasses()
.that().resideInAPackage("..adapter..")
.should().dependOnClassesThat()
.resideInAPackage("..infrastructure..")
.because("Adapter 必须通过 App 层访问基础设施");
// ── P1: 包命名合规 ──
@ArchTest
static final ArchRule domain_no_controller =
noClasses()
.that().resideInAPackage("..domain..")
.should().resideInAPackage("..controller..")
.because("Controller 属于 Adapter 层");
@ArchTest
static final ArchRule adapter_no_repository =
noClasses()
.that().resideInAPackage("..adapter..")
.should().resideInAPackage("..repository..")
.because("Repository 属于 Domain 或 Infrastructure 层");
}Maven 依赖
<dependency>
<groupId>com.tngtech.archunit</groupId>
<artifactId>archunit-junit5</artifactId>
<version>1.2.0</version>
<scope>test</scope>
</dependency>CI/CD 集成
GitHub Actions
name: COLA Architecture Check
on: [push, pull_request]
jobs:
architecture-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Run Architecture Tests
run: mvn test -Dtest=ArchitectureComplianceTest
- name: Check Score
run: python scripts/check_cola.py .GitLab CI
cola-architecture-check:
stage: test
image: eclipse-temurin:17
script:
- mvn test -Dtest=ArchitectureComplianceTest
- python3 scripts/check_cola.py .
only:
- merge_requests
- main运行方式
# 本地运行
mvn test -Dtest=ArchitectureComplianceTest
# Python 轻量校验(无需编译)
python scripts/check_cola.py src/
# 查看评分
# 输出示例:
# 模块: adapter, app, domain, infrastructure, start
# 违规: 2 (P0:0, P1:2)
# 评分: 90 → A(优秀)COLA 项目规模示例:单体简单项目
适用场景:小型单体应用,单一业务域,2-5 人团队,CRUD 为主,无需微服务拆分。
项目目录树
order-service/ # 单体项目,spring-boot-maven-plugin 打包
├── pom.xml # 单模块,无多模块划分
├── src/
│ ├── main/java/com/example/order/
│ │ ├── OrderApplication.java # @SpringBootApplication + @EnableCola 启动入口
│ │ │
│ │ ├── adapter/ # 适配层
│ │ │ ├── web/
│ │ │ │ ├── OrderController.java
│ │ │ │ └── dto/
│ │ │ │ ├── OrderCreateRequest.java
│ │ │ │ └── OrderResponse.java
│ │ │ └── advice/
│ │ │ └── GlobalExceptionHandler.java
│ │ │
│ │ ├── app/ # 应用层
│ │ │ ├── executor/
│ │ │ │ ├── command/
│ │ │ │ │ └── OrderCreateCmdExe.java
│ │ │ │ └── query/
│ │ │ │ └── OrderGetQryExe.java
│ │ │ └── model/
│ │ │ ├── command/
│ │ │ │ └── OrderCreateCmd.java
│ │ │ └── query/
│ │ │ └── OrderGetQry.java
│ │ │
│ │ ├── domain/ # 领域层 ★ 零框架依赖
│ │ │ ├── model/
│ │ │ │ ├── Order.java # 聚合根
│ │ │ │ ├── OrderItem.java # 实体
│ │ │ │ ├── OrderId.java # 值对象
│ │ │ │ ├── OrderStatus.java # 枚举
│ │ │ │ ├── Money.java # 值对象
│ │ │ │ └── event/
│ │ │ │ ├── OrderCreatedEvent.java
│ │ │ │ └── OrderPaidEvent.java
│ │ │ └── repository/
│ │ │ └── OrderRepository.java # 仓储接口
│ │ │
│ │ └── infrastructure/ # 基础设施层
│ │ ├── config/
│ │ │ └── DataSourceConfig.java
│ │ ├── persistence/
│ │ │ ├── OrderRepositoryImpl.java
│ │ │ ├── OrderMapper.java # MyBatis Mapper
│ │ │ ├── OrderPO.java # 持久化对象
│ │ │ └── OrderConverter.java # PO ↔ DO 转换
│ │ └── util/
│ │ └── SnowflakeIdGenerator.java
│ │
│ ├── main/resources/
│ │ ├── application.yml
│ │ └── db/migration/
│ │ └── V1__create_order_table.sql
│ └── test/java/com/example/order/
│ ├── ArchitectureComplianceTest.java # ArchUnit 校验
│ └── domain/
│ └── OrderTest.java包结构说明
| 包 | 内容 | 说明 |
|---|---|---|
adapter/ | Controller、DTO、ExceptionHandler | HTTP 协议适配,请求/响应转换 |
app/ | Command/Query Executor | 用例编排,事务管理 |
domain/ | Entity、VO、Aggregate、Repository 接口 | 核心业务逻辑,零框架依赖 |
infrastructure/ | RepositoryImpl、Mapper、PO、Config | 持久化实现、外部调用、配置 |
COLA 四层职责分工
| 层 | 职责 | 禁止事项 |
|---|---|---|
| Adapter | 接收 HTTP 请求,DTO 校验与转换,调用 App 层 | 禁止包含业务逻辑、禁止直接操作 Mapper |
| Application | 用例编排,事务边界控制,领域事件发布 | 禁止包含业务 if/else 判断 |
| Domain ★ | 实体行为、值对象不变性、领域事件定义 | 禁止依赖 Spring/MyBatis/JPA |
| Infrastructure | Repository 实现,PO↔Domain 转换,外部服务调用 | 禁止包含业务规则 |
模块间依赖关系
┌──────────┐
│ adapter │────依赖──→┐
└──────────┘ │
▼
┌──────────┐ ┌──────────┐
│ app │────→│ domain │←────┌──────────────────┐
└──────────┘ └──────────┘ │ infrastructure │
└──────────────────┘依赖方向:adapter → app → domain ← infrastructure
适用场景
- 项目总代码量 < 5 万行
- 单一业务上下文(如订单服务只有一个 Bounded Context)
- 团队 2-5 人,后端开发 1-3 人
- 无微服务拆分需求
- 快速原型验证 / MVP 阶段
- CRUD 操作为主,业务规则较简单
优点
- 结构简单,新人快速上手
- 构建速度快,无模块间编译依赖
- 单 jar 部署,运维成本低
- 开发初期迭代效率高
缺点
- 无法按模块限制依赖方向(需 ArchUnit 强制)
- 代码量增大后包内文件过多
- 不易拆分为微服务
COLA 项目规模示例:单体复杂项目
适用场景:中型单体应用,多聚合根,多业务上下文,5-15 人团队,有复杂业务编排需求。
项目目录树
mall-service/ # 单体项目,多聚合
├── pom.xml
├── src/main/java/com/example/mall/
│ ├── MallApplication.java # @SpringBootApplication + @EnableCola
│ │
│ ├── adapter/ # 适配层
│ │ ├── web/
│ │ │ ├── order/
│ │ │ │ └── OrderController.java
│ │ │ ├── product/
│ │ │ │ └── ProductController.java
│ │ │ ├── customer/
│ │ │ │ └── CustomerController.java
│ │ │ ├── payment/
│ │ │ │ └── PaymentController.java
│ │ │ └── dto/
│ │ │ ├── common/
│ │ │ │ ├── PageRequest.java
│ │ │ │ └── ApiResponse.java
│ │ │ ├── order/
│ │ │ │ ├── OrderCreateRequest.java
│ │ │ │ └── OrderResponse.java
│ │ │ └── product/
│ │ │ └── ProductResponse.java
│ │ ├── job/ # 定时任务
│ │ │ ├── OrderExpireJob.java
│ │ │ └── DailyReportJob.java
│ │ ├── message/ # MQ 消费者
│ │ │ ├── PaymentResultConsumer.java
│ │ │ └── InventoryChangeConsumer.java
│ │ └── rpc/ # RPC 接口
│ │ └── OrderQueryFacade.java
│ │
│ ├── app/ # 应用层
│ │ ├── executor/
│ │ │ ├── command/
│ │ │ │ ├── order/
│ │ │ │ │ ├── OrderCreateCmdExe.java
│ │ │ │ │ ├── OrderCancelCmdExe.java
│ │ │ │ │ └── OrderPayCmdExe.java
│ │ │ │ ├── product/
│ │ │ │ │ └── ProductDeductStockCmdExe.java
│ │ │ │ └── customer/
│ │ │ │ └── CustomerRegisterCmdExe.java
│ │ │ ├── query/
│ │ │ │ ├── order/
│ │ │ │ │ ├── OrderDetailQryExe.java
│ │ │ │ │ └── OrderListQryExe.java
│ │ │ │ └── product/
│ │ │ │ └── ProductSearchQryExe.java
│ │ │ └── event/
│ │ │ └── handler/
│ │ │ ├── PaymentCompletedHandler.java
│ │ │ └── InventoryDeductedHandler.java
│ │ ├── model/
│ │ │ ├── command/
│ │ │ │ ├── order/
│ │ │ │ │ ├── OrderCreateCmd.java
│ │ │ │ │ ├── OrderCancelCmd.java
│ │ │ │ │ └── OrderPayCmd.java
│ │ │ │ └── product/
│ │ │ │ └── ProductDeductStockCmd.java
│ │ │ ├── query/
│ │ │ │ ├── order/
│ │ │ │ │ ├── OrderDetailQry.java
│ │ │ │ │ └── OrderListQry.java
│ │ │ │ └── product/
│ │ │ │ └── ProductSearchQry.java
│ │ │ └── dto/
│ │ │ ├── OrderDTO.java
│ │ │ └── ProductDTO.java
│ │ ├── service/ # 非 CQRS 的服务编排
│ │ │ ├── OrderPlacementService.java # 下单流程编排:校验+锁库存+创建订单+发事件
│ │ │ └── PaymentReconciliationService.java # 对账编排
│ │ └── extension/ # COLA 扩展点
│ │ ├── point/
│ │ │ └── PaymentMethodExtPt.java # 支付方式扩展点
│ │ └── impl/
│ │ ├── AlipayPaymentExtension.java
│ │ └── WechatPaymentExtension.java
│ │
│ ├── domain/ # 领域层 ★
│ │ ├── order/ # 订单聚合
│ │ │ ├── Order.java # 聚合根
│ │ │ ├── OrderItem.java # 实体
│ │ │ ├── OrderId.java # 值对象
│ │ │ ├── OrderStatus.java # 枚举
│ │ │ ├── event/
│ │ │ │ ├── OrderCreatedEvent.java
│ │ │ │ ├── OrderPaidEvent.java
│ │ │ │ └── OrderCancelledEvent.java
│ │ │ └── repository/
│ │ │ └── OrderRepository.java
│ │ ├── product/ # 商品聚合
│ │ │ ├── Product.java
│ │ │ ├── ProductId.java
│ │ │ ├── Stock.java # 值对象
│ │ │ ├── Category.java
│ │ │ └── repository/
│ │ │ └── ProductRepository.java
│ │ ├── customer/ # 客户聚合
│ │ │ ├── Customer.java
│ │ │ ├── CustomerId.java
│ │ │ ├── Address.java
│ │ │ └── repository/
│ │ │ └── CustomerRepository.java
│ │ ├── payment/ # 支付领域(弱实体)
│ │ │ ├── Payment.java
│ │ │ ├── PaymentId.java
│ │ │ ├── PaymentResult.java
│ │ │ └── repository/
│ │ │ └── PaymentRepository.java
│ │ ├── shared/ # 共享值对象
│ │ │ ├── Money.java
│ │ │ ├── Quantity.java
│ │ │ └── Pageable.java
│ │ ├── gateway/ # 防腐层接口
│ │ │ ├── InventoryGateway.java
│ │ │ └── PaymentGateway.java
│ │ └── ability/ # 领域能力 (v5)
│ │ ├── StockReservationAbility.java
│ │ └── PriceCalculationAbility.java
│ │
│ └── infrastructure/ # 基础设施层
│ ├── config/
│ │ ├── DataSourceConfig.java
│ │ ├── CacheConfig.java
│ │ ├── MQConfig.java
│ │ └── RpcConfig.java
│ ├── persistence/
│ │ ├── order/
│ │ │ ├── OrderRepositoryImpl.java
│ │ │ ├── OrderMapper.java
│ │ │ ├── OrderPO.java
│ │ │ └── OrderConverter.java
│ │ ├── product/
│ │ │ ├── ProductRepositoryImpl.java
│ │ │ ├── ProductMapper.java
│ │ │ ├── ProductPO.java
│ │ │ └── ProductConverter.java
│ │ ├── customer/
│ │ │ ├── CustomerRepositoryImpl.java
│ │ │ ├── CustomerMapper.java
│ │ │ ├── CustomerPO.java
│ │ │ └── CustomerConverter.java
│ │ └── payment/
│ │ ├── PaymentRepositoryImpl.java
│ │ ├── PaymentMapper.java
│ │ ├── PaymentPO.java
│ │ └── PaymentConverter.java
│ ├── gatewayimpl/
│ │ ├── InventoryGatewayImpl.java # 调用外部库存系统
│ │ └── PaymentGatewayImpl.java # 调用微信/支付宝
│ ├── external/
│ │ ├── WechatPayClient.java
│ │ ├── AlipayClient.java
│ │ └── LogisticsClient.java
│ └── component/
│ ├── DistributedLock.java
│ └── RateLimiter.java包结构说明
| 包 | 内容 | 说明 |
|---|---|---|
adapter/ | 按业务域分组的 Controller + 消息消费者 + 定时任务 + RPC Facade | 多协议适配入口 |
app/ | 按业务域分组的 Executor + Service + Extension | 复杂业务编排,扩展点路由 |
domain/ | 按聚合根分组的 Entity/VO/Repository 接口 + Shared 共享值对象 | 多聚合,聚合间通过 ID 引用 |
infrastructure/ | 按业务域分组的 RepositoryImpl/Mapper/PO + 公共组件 | 持久化实现 + 外部服务 + 基础设施组件 |
COLA 四层职责分工
| 层 | 职责 | 复杂单体特殊注意 |
|---|---|---|
| Adapter | 多协议适配 (HTTP/MQ/RPC/Job) | 按业务域分 controller 包,避免单文件过大 |
| Application | 跨聚合业务编排、事件驱动流程 | app/service/ 承担 Saga 编排,Executor 只做单聚合操作 |
| Domain ★ | 多聚合独立建模,聚合间通过 ID 间接引用 | 严禁跨聚合对象直接引用 (如 Order.getCustomer()) |
| Infrastructure | 多数据源、外部服务调用、分布式组件 | PO 与 Domain 必须分离,用 Converter 转换 |
模块间依赖关系
┌─────────────────────────────────┐
│ adapter │
│ HTTP / MQ / RPC / Job │
└───────────────┬─────────────────┘
│ depends
▼
┌─────────────────────────────────┐
│ app │
│ Executor / Service / Extension │
└───────┬─────────────────────────┘
│ depends
▼
┌─────────────────────────────────┐
│ domain ★ │
│ Order / Product / Customer / │
│ Payment / Shared │
└─────────────────────────────────┘
▲
│ depends
┌───────────────┴─────────────────┐
│ infrastructure │
│ RepositoryImpl / Gateway / │
│ External / Component │
└─────────────────────────────────┘依赖方向:adapter → app → domain ← infrastructure
聚合间依赖约束:订单聚合通过 ProductId 引用商品,不直接持有 Product 对象。
适用场景
- 项目总代码量 5-15 万行
- 多个 Bounded Context 但共享同一数据库(演进阶段)
- 有复杂业务编排(下单流程涉及订单+库存+支付+物流)
- 团队 5-15 人,后端开发 3-8 人
- 业务规则较复杂,多聚合交互频繁
- 未来可能拆分为微服务,但目前各聚合内聚在单体中
优点
- 多聚合在单体中紧密协作,无需 RPC 开销
- 事务管理简单(同数据库本地事务)
- 相比单聚合单体,代码组织更清晰
- 为未来微服务拆分做包级别准备
缺点
- App 层编排可能随着业务增长变得复杂(需引入 Saga 模式)
- 单 jar 体积增大,冷启动耗时增加
- 多团队协作时 Git 冲突增加
- 无法独立部署单一聚合
COLA 项目规模示例:单体多模块项目
适用场景:中型单体应用,需要 Maven 多模块强制隔离依赖方向,5-15 人团队,对架构约束要求高。
项目目录树
order-system/ # 父 POM,packaging=pom
├── pom.xml # 父 POM,定义 modules + dependencyManagement
│
├── order-start/ # 启动模块
│ ├── pom.xml # 依赖所有其他模块,含 spring-boot-maven-plugin
│ └── src/main/java/com/example/order/
│ ├── OrderApplication.java # @SpringBootApplication + @EnableCola
│ └── config/
│ ├── CorsConfig.java
│ └── SwaggerConfig.java
│
├── order-adapter/ # 适配层模块
│ ├── pom.xml # 依赖 order-app、order-domain
│ └── src/main/java/com/example/order/adapter/
│ ├── web/
│ │ ├── OrderController.java
│ │ └── dto/
│ │ ├── OrderCreateRequest.java
│ │ └── OrderResponse.java
│ ├── rpc/
│ │ └── OrderQueryFacade.java
│ └── advice/
│ └── GlobalExceptionHandler.java
│
├── order-app/ # 应用层模块
│ ├── pom.xml # 依赖 order-domain、order-infrastructure
│ └── src/main/java/com/example/order/app/
│ ├── executor/
│ │ ├── command/
│ │ │ └── OrderCreateCmdExe.java
│ │ └── query/
│ │ └── OrderGetQryExe.java
│ ├── model/
│ │ ├── command/
│ │ │ └── OrderCreateCmd.java
│ │ └── query/
│ │ └── OrderGetQry.java
│ ├── service/
│ │ └── OrderPlacementService.java
│ └── assembler/
│ └── OrderAssembler.java
│
├── order-domain/ # 领域层模块 ★ 零 external 依赖
│ ├── pom.xml # 零外部依赖(仅 lombok、validation-api)
│ └── src/main/java/com/example/order/domain/
│ ├── model/
│ │ ├── Order.java # 聚合根
│ │ ├── OrderItem.java # 实体
│ │ ├── OrderId.java # 值对象
│ │ ├── OrderStatus.java
│ │ ├── Money.java
│ │ └── event/
│ │ ├── OrderCreatedEvent.java
│ │ └── OrderPaidEvent.java
│ ├── repository/
│ │ └── OrderRepository.java # 仓储接口
│ ├── gateway/
│ │ └── InventoryGateway.java # 防腐层接口
│ └── ability/
│ └── PriceCalculationAbility.java
│
├── order-infrastructure/ # 基础设施层模块
│ ├── pom.xml # 依赖 order-domain
│ └── src/main/java/com/example/order/infrastructure/
│ ├── config/
│ │ ├── DataSourceConfig.java
│ │ └── CacheConfig.java
│ ├── persistence/
│ │ ├── OrderRepositoryImpl.java
│ │ ├── OrderMapper.java
│ │ ├── OrderPO.java
│ │ └── OrderConverter.java
│ └── gatewayimpl/
│ └── InventoryGatewayImpl.java
│
└── order-common/ # 公共模块(可选)
├── pom.xml # 无内部模块依赖
└── src/main/java/com/example/order/common/
├── constant/
│ └── BizConstants.java
├── exception/
│ ├── BizException.java
│ └── ErrorCode.java
└── context/
└── UserContext.java各模块的包结构说明
| 模块 | 包路径 | 内容 | Maven ArtifactId |
|---|---|---|---|
| 启动模块 | com.example.order | Application 启动类 + 全局配置 | order-start |
| 适配层 | com.example.order.adapter | Controller / RPC / DTO / ExceptionHandler | order-adapter |
| 应用层 | com.example.order.app | Executor / Service / Assembler / Model | order-app |
| 领域层 | com.example.order.domain | Entity / VO / Aggregate / Repository 接口 | order-domain |
| 基础设施层 | com.example.order.infrastructure | RepositoryImpl / Mapper / PO / GatewayImpl | order-infrastructure |
| 公共模块 | com.example.order.common | 常量 / 异常基类 / 上下文 / 工具 | order-common |
COLA 四层职责分工
| 层 | 对应模块 | 职责 | Maven 依赖约束 |
|---|---|---|---|
| Adapter | order-adapter | HTTP/RPC 协议适配,DTO 转换 | 可引用 app + domain + common |
| Application | order-app | 用例编排,事务管理,扩展点 | 可引用 domain + infrastructure + common |
| Domain ★ | order-domain | 核心业务规则 | 零外部依赖,仅可引用 common |
| Infrastructure | order-infrastructure | 持久化、外部服务、组件 | 可引用 domain + common |
| 启动 | order-start | 启动入口、全局配置 | 引用所有其他模块 |
| 公共 | order-common | 常量、异常、上下文 | 无项目内依赖 |
模块间依赖关系图
┌──────────────────────────────────────────────────────────────────┐
│ order-start │
│ (启动模块 — 引用所有其他模块) │
└────┬───────────┬──────────┬──────────┬──────────┬───────────────┘
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ adapter │ │ app │ │ domain │ │ infra │ │ common │
│ │ │ │ │ ★ │ │ │ │ │
└────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ └─────────┘
│ │ │ │ ▲
│ ┌────┘ │ │ │
│ │ │ │ │
▼ ▼ ▼ ▼ │
┌───────────────────────────────────────────────────┐│
│ Maven 依赖关系图 ││
│ ││
│ adapter ───→ app ───→ domain ←─── infrastructure ││
│ │ │ ▲ │ ││
│ └────┬────┘ │ │ ││
│ └──────────────┼──────────────┘ ││
│ └── common ←──────────────┘│
└────────────────────────────────────────────────────┘硬约束(由 Maven compile-scope 依赖保证):
order-domain的 pom.xml 中不出现order-adapter、order-app、order-infrastructure、spring-boot-starter、mybatis-spring-boot-starter等依赖order-app不直接引用order-adapterorder-infrastructure不引用order-app、order-adapter
验证方式:
<!-- order-domain/pom.xml: 领域层只能依赖这些 -->
<dependency>
<groupId>com.example.order</groupId>
<artifactId>order-common</artifactId>
</dependency>
<!-- 不允许出现 spring-boot-starter、mybatis、jpa 等 -->适用场景
- 需要 Maven 模块编译时强制依赖约束(比 ArchUnit 更早发现问题)
- 团队 5-15 人,多人并行开发同一项目
- 业务复杂度中等,单一 Bounded Context 但有丰富行为
- 需要确保架构不被新手开发者破坏
- 单个 Git 仓库管理,不想拆分为多仓库
优点
- Maven 编译时即发现依赖违规(比 ArchUnit 运行时更早)
- 各模块独立编译,仅需重新编译变更模块
- 团队可按模块分工(Domain 资深开发 / Infra 一般开发)
- 为未来微服务拆分做模块级准备
缺点
- 模块间接口变化影响编译范围增大
- Maven 多模块构建时间比单模块长
- 新手需要理解模块间的接口抽象(如 Repository 接口在 Domain,实现在 Infra)
- Common 模块容易变成"垃圾桶"(需严格控制内容)
COLA 项目规模示例:微服务简单的单体项目
适用场景:微服务架构,每个微服务内部采用 COLA 单体结构(非多模块),服务边界清晰,业务简单。
项目目录树
├── order-service/ # 订单微服务 (COLA 单体)
│ ├── pom.xml
│ └── src/main/java/com/example/order/
│ ├── OrderApplication.java
│ ├── adapter/
│ │ ├── web/OrderController.java # 对前端暴露 REST
│ │ └── rpc/OrderQueryFacade.java # 对其他微服务暴露 Dubbo/gRPC
│ ├── app/
│ │ ├── executor/command/OrderCreateCmdExe.java
│ │ └── executor/query/OrderGetQryExe.java
│ ├── domain/
│ │ ├── Order.java
│ │ ├── OrderItem.java
│ │ └── repository/OrderRepository.java
│ └── infrastructure/
│ ├── persistence/OrderRepositoryImpl.java
│ └── external/ProductServiceClient.java # 调用商品微服务
│
├── product-service/ # 商品微服务 (COLA 单体)
│ ├── pom.xml
│ └── src/main/java/com/example/product/
│ ├── ProductApplication.java
│ ├── adapter/
│ │ ├── web/ProductController.java
│ │ └── rpc/ProductRpcFacade.java
│ ├── app/
│ │ ├── executor/command/ProductCreateCmdExe.java
│ │ └── executor/query/ProductSearchQryExe.java
│ ├── domain/
│ │ ├── Product.java
│ │ ├── Stock.java
│ │ └── repository/ProductRepository.java
│ └── infrastructure/
│ ├── persistence/ProductRepositoryImpl.java
│ └── search/ProductElasticsearchRepo.java
│
├── customer-service/ # 客户微服务 (COLA 单体)
│ ├── pom.xml
│ └── src/main/java/com/example/customer/
│ ├── CustomerApplication.java
│ ├── adapter/
│ │ └── web/CustomerController.java
│ ├── app/
│ │ └── executor/command/CustomerRegisterCmdExe.java
│ ├── domain/
│ │ ├── Customer.java
│ │ └── repository/CustomerRepository.java
│ └── infrastructure/
│ └── persistence/CustomerRepositoryImpl.java
│
├── gateway-service/ # API 网关 (可选)
│ └── ...
│
└── common/ # 公共组件(共享 DTO、工具类)
├── common-api/ # 服务间通信 DTO
│ ├── OrderDTO.java
│ └── ProductDTO.java
└── common-util/
├── ApiResponse.java
└── BizException.java各服务的包结构说明
每个微服务内部采用与示例 06 相同的 COLA 单体包结构:
| 微服务 | Adapter 协议 | 领域聚合 | 对外依赖 |
|---|---|---|---|
order-service | REST + Dubbo RPC | Order + OrderItem | product-service, customer-service |
product-service | REST + Dubbo RPC | Product + Stock | — (被调用方) |
customer-service | REST | Customer | — (被调用方) |
COLA 四层职责分工
| 层 | 职责 | 微服务环境特殊注意 |
|---|---|---|
| Adapter | REST (对外) + RPC/Dubbo (服务间) + MQ Consumer | Adapter 同时暴露 Web API 和 RPC API |
| Application | 单聚合用例编排 | 涉及调用其他微服务时通过 Gateway/防腐层,不在 Executor 直接调用 |
| Domain ★ | 服务内的业务规则 | 聚合不可直接引用其他微服务的 Domain 对象 |
| Infrastructure | 本地持久化 + 外部微服务调用 | external/ 封装对其他微服务的调用,不暴露技术细节 |
服务间依赖关系
┌──────────────────┐
│ order-service │
│ │
│ adapter (REST) │←─ 前端请求
│ adapter (RPC) │←─ 其他服务调用
│ app │
│ domain │
│ infra (DB + │
│ FeignClient │─────── 调用 ───────┐
│ → ProductSvc) │ │
└──────────────────┘ │
▼
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ customer-service │ │ product-service │ │ common-api │
│ │ │ │ │ │
│ adapter (REST) │ │ adapter (REST) │ │ 共享 DTO │
│ app │ │ adapter (RPC) │ │ OrderDTO │
│ domain │ │ app │ │ ProductDTO │
│ infra │ │ domain │ │ ApiResponse │
└──────────────────┘ │ infra │ └──────────────────┘
└──────────────────┘依赖原则:
- 每个微服务独立数据库,不共享表
- 服务间通过 RPC/MQ 通信,不直接访问对方数据库
common-api发布为 Maven 坐标,各服务通过依赖引用共享 DTO- 服务内的 COLA 分层规则不变:Domain 仍然零框架依赖
适用场景
- 微服务已经拆分完成,每个服务职责单一
- 每个微服务代码量 < 3 万行
- 每个微服务内业务逻辑相对简单(1-2 个聚合)
- 服务间通过 RPC (Dubbo/gRPC) 或 MQ (RocketMQ/Kafka) 通信
- 团队 10-30 人,每个服务由 2-3 人小团队负责
优点
- 每个服务简单,新人快速上手
- 独立部署、独立扩缩容
- 单模块构建快,CI 效率高
- 技术栈可按服务选择(如商品服务用 Elasticsearch,订单服务用 MySQL)
缺点
- 服务内无法用编译时约束防止架构腐化(单模块)
common-api修改影响所有服务- 需要处理分布式事务(Saga/最终一致性)
- 服务数量增多后运维成本高
COLA 项目规模示例:微服务复杂的单体项目
适用场景:微服务架构,网关/核心服务内部采用 COLA 单体结构,基础设施复杂(认证、限流、加密、路由),基于 ddd4j-gateway 真实结构。
参考项目
本示例基于真实项目 ddd4j-gateway(io.ddd4j:ddd4j-gateway)的结构提取。
项目目录树
ddd4j-gateway/ # API 网关微服务 — 单体 COLA 结构
├── pom.xml # 继承 ddd4j-boot-parent
│ # 依赖:spring-boot, spring-cloud-gateway,
│ # sa-token, redisson, fastjson2,
│ # guava, hutool, kaptcha, commons-lang3
├── src/
│ ├── main/java/io/ddd4j/gateway/
│ │ │
│ │ ├── start/ # 启动 + 装配
│ │ │ ├── GatewayApplication.java # @EnableCola 启动类
│ │ │ └── assembler/
│ │ │ └── GatewayAssembler.java # 启动时的组件装配
│ │ │
│ │ ├── adapter/ # 适配层 (6 个 Java 文件)
│ │ │ ├── web/
│ │ │ │ ├── route/
│ │ │ │ │ └── GatewayRouteController.java # 路由管理 REST 接口
│ │ │ │ └── dto/
│ │ │ │ ├── request/
│ │ │ │ │ ├── RouteSaveRequest.java
│ │ │ │ │ └── CryptoKeyRequest.java
│ │ │ │ └── response/
│ │ │ │ ├── RouteResponse.java
│ │ │ │ └── CryptoKeyResponse.java
│ │ │ └── advice/
│ │ │ └── GlobalExceptionHandler.java # 统一异常处理
│ │ │
│ │ ├── app/ # 应用层 (11 个 Java 文件)
│ │ │ ├── executor/
│ │ │ │ ├── command/ # 命令执行器
│ │ │ │ │ ├── crypto/
│ │ │ │ │ │ ├── GenerateKeyCmdExe.java # 生成密钥
│ │ │ │ │ │ └── RotateKeyCmdExe.java # 密钥轮转
│ │ │ │ │ └── route/
│ │ │ │ │ ├── SaveRouteCmdExe.java # 保存路由配置
│ │ │ │ │ └── RefreshRouteCmdExe.java # 刷新路由缓存
│ │ │ │ └── query/ # 查询执行器
│ │ │ │ ├── crypto/
│ │ │ │ │ └── QueryKeyQryExe.java
│ │ │ │ └── route/
│ │ │ │ └── QueryRouteQryExe.java
│ │ │ ├── model/ # 命令/查询/DTO 对象
│ │ │ │ ├── command/
│ │ │ │ │ ├── GenerateKeyCmd.java
│ │ │ │ │ ├── SaveRouteCmd.java
│ │ │ │ │ └── RefreshRouteCmd.java
│ │ │ │ └── query/
│ │ │ │ ├── QueryKeyQry.java
│ │ │ │ └── QueryRouteQry.java
│ │ │ ├── handler/ # 处理器
│ │ │ │ └── GatewayRouteHandler.java
│ │ │ ├── extension/ # COLA 扩展点
│ │ │ │ └── RateLimitExtension.java
│ │ │ └── config/
│ │ │ └── AppConfig.java
│ │ │
│ │ ├── domain/ # 领域层 ★ (30 个 Java 文件)
│ │ │ ├── repository/ # 仓储接口
│ │ │ │ ├── RouteRepository.java # 路由仓储
│ │ │ │ └── CryptoKeyRepository.java # 密钥仓储
│ │ │ └── util/
│ │ │ ├── RouteValidator.java # 路由校验逻辑
│ │ │ └── CryptoAlgorithm.java # 加密算法领域逻辑
│ │ │
│ │ └── infrastructure/ # 基础设施层 (52 个 Java 文件)
│ │ ├── config/ # 配置
│ │ │ ├── GatewayConfig.java
│ │ │ ├── RedisConfig.java
│ │ │ └── ThreadPoolConfig.java
│ │ ├── component/ # 技术组件
│ │ │ ├── crypto/ # 加密组件
│ │ │ │ ├── CryptoComponent.java # 加解密主组件
│ │ │ │ ├── cache/
│ │ │ │ │ └── CryptoKeyCache.java # 密钥缓存
│ │ │ │ └── strategy/
│ │ │ │ ├── AesCryptoStrategy.java
│ │ │ │ └── RsaCryptoStrategy.java
│ │ │ ├── ratelimit/ # 限流组件
│ │ │ │ ├── RateLimitManager.java
│ │ │ │ └── key/
│ │ │ │ ├── IpRateLimitKeyResolver.java
│ │ │ │ └── UserRateLimitKeyResolver.java
│ │ │ ├── satoken/ # 认证/鉴权
│ │ │ │ ├── SaTokenConfig.java
│ │ │ │ └── StpInterfaceImpl.java
│ │ │ ├── filter/ # 网关过滤器 (Spring Cloud Gateway)
│ │ │ │ ├── log/
│ │ │ │ │ └── AccessLogFilter.java
│ │ │ │ ├── global/
│ │ │ │ │ ├── AuthGlobalFilter.java
│ │ │ │ │ └── RateLimitGlobalFilter.java
│ │ │ │ ├── factory/
│ │ │ │ │ └── CryptoGatewayFilterFactory.java
│ │ │ │ └── gateway/
│ │ │ │ └── RouteCacheGatewayFilter.java
│ │ │ └── error/
│ │ │ └── GatewayErrorHandler.java
│ │ ├── constant/ # 常量
│ │ │ └── redis/
│ │ │ └── RedisKeyConstants.java
│ │ ├── persistence/ # 持久化
│ │ │ ├── RouteRepositoryImpl.java
│ │ │ └── CryptoKeyRepositoryImpl.java
│ │ └── util/
│ │ ├── IpUtils.java
│ │ └── RouteUtils.java
│ │
│ ├── main/resources/
│ │ ├── application.yml # 主配置
│ │ ├── i18n/ # 国际化
│ │ │ ├── messages_zh_CN.properties
│ │ │ └── messages_en_US.properties
│ │ └── conf/
│ │ └── logback-spring.xml
│ └── test/java/io/ddd4j/gateway/
│ └── start/
│ └── GatewayApplicationTest.java包结构分析
ddd4j-gateway 是典型的"微服务复杂的单体"COLA 项目,具有以下特点:
| 层级 | 文件数 | 复杂度特征 |
|---|---|---|
| start | 2 | 标准启动入口,带 Assembler 组件装配 |
| adapter | 6 | REST 接口少,主要是路由管理和密钥管理 |
| app | 11 | CQRS 执行器分离,按 crypto/route 子域分组 |
| domain | 30 | 领域对象丰富,Repository 接口 + 领域工具类 |
| infrastructure | 52 | 最复杂层:加密/限流/认证/过滤器/持久化等大量技术组件 |
文件分布比例:infrastructure(52) > domain(30) > app(11) > adapter(6) > start(2)
COLA 四层职责分工
| 层 | 职责 | 网关服务特殊性 |
|---|---|---|
| Adapter | 路由管理 API、密钥管理 API | 网关的 Adapter 提供管理面 REST 接口,数据面由 Spring Cloud Gateway 过滤器处理 |
| Application | 路由和密钥的 CRUD 编排、缓存刷新 | 命令执行器内触发路由刷新、密钥轮转等副作用 |
| Domain ★ | 路由校验规则、加密算法选择 | 网关的路由合法性校验、加密策略选择体现在领域层 |
| Infrastructure | 过滤器链、加密实现(AES/RSA)、限流、认证(Sa-Token)、Redis 缓存 | Gateway 高度依赖过滤器链路,Infrastructure 承载大量技术基础设施 |
模块间依赖关系
┌─────────┐ ┌──────────┐
│ start │────→│ adapter │
└─────────┘ └────┬─────┘
│
▼
┌────────────────────────────────────┐
│ app │
│ GenerateKeyCmdExe │
│ SaveRouteCmdExe │
│ RefreshRouteCmdExe │
│ QueryKeyQryExe / QueryRouteQryExe │
└──────┬─────────────────────────────┘
│
▼
┌──────────────────────────────────────────────┐
│ domain ★ │
│ RouteRepository (接口) │
│ CryptoKeyRepository (接口) │
│ RouteValidator / CryptoAlgorithm │
└──────────────────────────────────────────────┘
▲
│
┌──────┴──────────────────────────────────────┐
│ infrastructure │
│ RouteRepositoryImpl │
│ CryptoKeyRepositoryImpl │
│ CryptoComponent (Aes/Rsa) │
│ RateLimitManager │
│ SaTokenConfig (认证) │
│ AuthGlobalFilter / RateLimitGlobalFilter │
│ CryptoGatewayFilterFactory │
└──────────────────────────────────────────────┘适用场景
- 网关类微服务(API Gateway / BFF),需要丰富的过滤器链
- 认证授权服务(OAuth2 / Sa-Token)
- 基础设施复杂度高(加密/限流/断路器/日志/链路追踪)
- 业务逻辑相对简单但技术组件非常丰富
- 单模块即可容纳所有功能区(Maven 多模块反而增加模块间协调成本)
ddd4j-gateway 的技术栈
| 组件 | 用途 | 所在层 |
|---|---|---|
| Spring Cloud Gateway | API 网关核心 | Infrastructure (filter/) |
| Sa-Token | 认证鉴权 | Infrastructure (component/satoken/) |
| Redisson | 分布式锁 + 缓存 | Infrastructure (component/crypto/cache/) |
| Fastjson2 | JSON 序列化 | 全局(common 依赖) |
| Guava | 本地缓存、集合工具 | Infrastructure (component/) |
| Hutool | 通用工具 | Infrastructure (util/) |
| Kaptcha | 验证码 | Infrastructure (component/) |
相比 ddd4j-rednote/ddd4j-pay 的区别
| 特征 | ddd4j-gateway (单体) | ddd4j-rednote/ddd4j-pay (多模块) |
|---|---|---|
| 模块数 | 1 | 5+ (含 BOM + Dependencies) |
| 业务复杂度 | 低(路由管理) | 中-高(业务领域) |
| 基础设施复杂度 | 极高(过滤器、加密、限流) | 中 |
| 适用场景 | 网关/基础设施服务 | 业务服务 |
优点
- 对于基础设施密集型微服务,单体结构避免模块间接口抽象开销
- 过滤器、组件、配置集中在同一代码库,调试方便
- 构建和部署简单(单 jar)
- Spring Cloud Gateway 的过滤器链天然适合在 Infrastructure 层实现
缺点
- Infrastructure 层文件过多(52/101 = 51%),需要严格 package 划分
- 纯业务逻辑少的服务容易演变为"重量级基础设施+空领域",违背 DDD 初衷
- 缺少 Maven 编译时依赖约束,需依赖 ArchUnit 运行时校验
COLA 项目规模示例:微服务简单的多模块项目
适用场景:微服务架构,每个业务服务内部采用 Maven 多模块 COLA 结构,业务简单但对架构约束有高要求,基于 ddd4j-rednote 真实结构。
参考项目
本示例基于真实项目 ddd4j-rednote(io.ddd4j.rednote:ddd4j-rednote)的结构提取。
项目目录树
ddd4j-rednote/ # 父 POM, packaging=pom
├── pom.xml # 继承 ddd4j-boot-parent, modules=4
│ <modules>
│ <module>ddd4j-rednote-bom</module>
│ <module>ddd4j-rednote-dependencies</module>
│ <module>ddd4j-rednote-api</module>
│ <module>ddd4j-rednote-common</module>
│ </modules>
│
├── ddd4j-rednote-bom/ # BOM (Bill of Materials)
│ └── pom.xml # 统一版本管理, packaging=pom
│
├── ddd4j-rednote-dependencies/ # 依赖管理
│ └── pom.xml # 集中管理外部依赖版本, packaging=pom
│
├── ddd4j-rednote-api/ # 业务接口模块 (聚合子模块)
│ ├── pom.xml # packaging=pom, modules=5
│ │ <modules>
│ │ <module>ddd4j-rednote-api-adapter</module>
│ │ <module>ddd4j-rednote-api-client</module>
│ │ <module>ddd4j-rednote-api-app</module>
│ │ <module>ddd4j-rednote-api-domain</module>
│ │ <module>ddd4j-rednote-api-infrastructure</module>
│ │ </modules>
│ │
│ ├── ddd4j-rednote-api-adapter/ # 适配层
│ │ ├── pom.xml # 依赖 api-app, api-domain
│ │ └── src/main/java/io/ddd4j/rednote/api/
│ │ └── adapter/
│ │ └── ... # Controller / RPC / DTO
│ │
│ ├── ddd4j-rednote-api-client/ # 客户端 SDK
│ │ ├── pom.xml # 依赖 api-domain (仅接口)
│ │ └── src/main/java/io/ddd4j/rednote/api/
│ │ └── client/
│ │ └── ... # Feign Client / Dubbo 接口
│ │
│ ├── ddd4j-rednote-api-app/ # 应用层
│ │ ├── pom.xml # 依赖 api-domain, api-infrastructure
│ │ └── src/main/java/io/ddd4j/rednote/api/
│ │ └── app/
│ │ └── ... # Executor / Service / Assembler
│ │
│ ├── ddd4j-rednote-api-domain/ # 领域层 ★
│ │ ├── pom.xml # 零外部依赖
│ │ └── src/main/java/io/ddd4j/rednote/api/
│ │ └── domain/
│ │ └── ... # Entity / VO / Repository 接口
│ │
│ └── ddd4j-rednote-api-infrastructure/ # 基础设施层
│ ├── pom.xml # 依赖 api-domain, common-infrastructure
│ └── src/main/java/io/ddd4j/rednote/api/
│ └── infrastructure/
│ └── ... # RepositoryImpl / Mapper / PO
│
└── ddd4j-rednote-common/ # 公共模块 (聚合子模块)
├── pom.xml # packaging=pom, modules=2
│ <modules>
│ <module>ddd4j-rednote-common-domain</module>
│ <module>ddd4j-rednote-common-infrastructure</module>
│ </modules>
│
├── ddd4j-rednote-common-domain/ # 公共领域对象
│ ├── pom.xml # 零外部依赖
│ └── src/main/java/io/ddd4j/rednote/common/
│ └── domain/
│ └── ... # 共享值对象、公共枚举
│
└── ddd4j-rednote-common-infrastructure/ # 公共基础设施
├── pom.xml # 依赖 common-domain
└── src/main/java/io/ddd4j/rednote/common/
└── infrastructure/
└── ... # 公共配置、工具类、组件模块结构总结
ddd4j-rednote 采用三级模块层级:
Level 1: ddd4j-rednote (父 POM)
├── Level 2: ddd4j-rednote-bom (版本管理)
├── Level 2: ddd4j-rednote-dependencies (依赖管理)
├── Level 2: ddd4j-rednote-api (业务接口聚合)
│ ├── Level 3: ddd4j-rednote-api-adapter
│ ├── Level 3: ddd4j-rednote-api-client ← 特有模块:给其他服务用的 SDK
│ ├── Level 3: ddd4j-rednote-api-app
│ ├── Level 3: ddd4j-rednote-api-domain
│ └── Level 3: ddd4j-rednote-api-infrastructure
└── Level 2: ddd4j-rednote-common (公共模块聚合)
├── Level 3: ddd4j-rednote-common-domain
└── Level 3: ddd4j-rednote-common-infrastructure总计 10 个 Maven 模块(含 pom 类型)。
各模块的包结构说明
| Level 2 模块 | Level 3 模块 | 包路径 | 职责 |
|---|---|---|---|
rednote-bom | — | — | 统一管理所有模块版本号 |
rednote-dependencies | — | — | 集中管理外部依赖版本 (scope=import) |
rednote-api | rednote-api-adapter | io.ddd4j.rednote.api.adapter | REST/RPC 适配 |
rednote-api | rednote-api-client | io.ddd4j.rednote.api.client | 其他微服务调用本服务的 Feign/Dubbo 接口 |
rednote-api | rednote-api-app | io.ddd4j.rednote.api.app | 用例编排 + CQRS |
rednote-api | rednote-api-domain | io.ddd4j.rednote.api.domain | 核心领域对象 + Repository 接口 |
rednote-api | rednote-api-infrastructure | io.ddd4j.rednote.api.infrastructure | 持久化 + 外部调用实现 |
rednote-common | rednote-common-domain | io.ddd4j.rednote.common.domain | 跨微服务共享的值对象、枚举 |
rednote-common | rednote-common-infrastructure | io.ddd4j.rednote.common.infrastructure | 共享配置、工具类 |
核心理念:rednote-api-client 模块是本项目的关键设计——它为其他微服务提供零依赖领域接口的 SDK,调用方只需依赖 client 模块即可调用本服务。
COLA 四层职责分工
| 层 | 对应模块 | 职责 | 微服务环境特点 |
|---|---|---|---|
| Adapter | api-adapter | HTTP/RPC 适配入口 | 同时提供 REST 和 Dubbo 协议 |
| Application | api-app | 用例编排 | 可依赖 common-infrastructure 使用共享组件 |
| Domain ★ | api-domain + common-domain | 核心领域 + 共享值对象 | api-domain 依赖 common-domain(唯一允许的领域间依赖) |
| Infrastructure | api-infrastructure + common-infrastructure | 持久化 + 共享工具 | 共享基础设施减少重复代码 |
模块间依赖关系图
ddd4j-rednote-bom ──────────────────────────────────────────────┐
ddd4j-rednote-dependencies ─────────────────────────────────────┤
│
┌────────────────────────────────────────────────────────────────┤
│ rednote-api │
│ │
│ ┌──────────────────────┐ │
│ │ api-adapter │ │
│ │ (REST/RPC 入口) │ │
│ └───────┬──────────────┘ │
│ │ depends │
│ ▼ │
│ ┌──────────────────────┐ │
│ │ api-app │───── depends ────┐ │
│ │ (用例编排) │ │ │
│ └───────┬──────────────┘ │ │
│ │ depends │ │
│ ▼ │ │
│ ┌──────────────────────┐ ▼ │
│ │ api-domain ★ │ ┌──────────────────────┐ │
│ │ (核心领域) │ │ api-infrastructure │ │
│ └───────┬──────────────┘ │ (持久化实现) │ │
│ │ depends └──────────────────────┘ │
│ ▼ │
│ ┌──────────────────────┐ │
│ │ api-client │← 其他微服务依赖此模块 │
│ │ (对外 SDK) │ │
│ └──────────────────────┘ │
│ │
├────────────────────────────────────────────────────────────────┤
│ rednote-common │
│ │
│ ┌──────────────────────┐ ┌──────────────────────────────┐ │
│ │ common-domain │ │ common-infrastructure │ │
│ │ (共享值对象) │──→ │ (共享配置/工具) │ │
│ └──────────────────────┘ └──────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘关键依赖规则:
api-domain→common-domain(领域层共享值对象)api-infrastructure→common-infrastructure(共享技术组件)api-client→api-domain(对外 SDK 仅暴露领域对象,不暴露基础设施)common-infrastructure→common-domain(基础设施依赖领域)
适用场景
- 微服务数量较多 (5+),需要一个服务提供 SDK 给其他服务调用
- 需要 Maven 编译时强制依赖约束
- 团队 5-15 人,对代码质量要求高
- 有跨微服务共享的公共值对象和工具
- BOM + Dependencies 统一管理全项目依赖版本
ddd4j-rednote 的设计精髓
1. BOM + Dependencies 双重版本管理:BOM 管理模块版本,Dependencies 管理外部依赖版本 2. Client 模块:为其他微服务提供类型安全的调用 SDK,避免硬编码 URL 3. Common 分层:Common 也按 Domain/Infrastructure 拆分,保持架构一致性 4. 三级模块层级:Parent → API/Common → COLA 四层,结构清晰
优点
- 编译时依赖约束(Maven 模块级隔离,比 ArchUnit 更早发现问题)
- Client 模块让其他服务调用方无需了解内部实现
- BOM + Dependencies 统一版本管理,避免依赖冲突
- Common 模块按分层拆分,避免 common 变"垃圾桶"
- 每个微服务可独立发布 Client 模块给依赖方
缺点
- 10 个 Maven 模块增加构建复杂度
- 新手需要理解模块间的依赖关系
- 模块间接口变化影响范围大
- BOM/Dependencies 维护需要专人负责
COLA 项目规模示例:微服务复杂的多模块项目
适用场景:大型微服务系统,多个业务域(如支付-API 和支付-Admin),每个业务域内部 Maven 多模块 COLA 结构,15-50 人团队,基于 ddd4j-pay 真实结构。
参考项目
本示例基于真实项目 ddd4j-pay(io.ddd4j.pay:ddd4j-pay)的结构提取。
项目目录树
ddd4j-pay/ # 父 POM, packaging=pom
├── pom.xml # 继承 ddd4j-boot-parent, modules=5
│ <modules>
│ <module>ddd4j-pay-bom</module>
│ <module>ddd4j-pay-dependencies</module>
│ <module>ddd4j-pay-api</module>
│ <module>ddd4j-pay-admin</module>
│ <module>ddd4j-pay-common</module>
│ </modules>
│
├── ddd4j-pay-bom/ # BOM
│ └── pom.xml # 统一版本管理
│
├── ddd4j-pay-dependencies/ # 依赖管理
│ └── pom.xml # 集中管理外部依赖版本
│
├── ddd4j-pay-api/ # 支付对外接口域 (Level 2)
│ ├── pom.xml # packaging=pom, modules=5
│ │ <modules>
│ │ <module>ddd4j-pay-api-adapter</module>
│ │ <module>ddd4j-pay-api-client</module>
│ │ <module>ddd4j-pay-api-app</module>
│ │ <module>ddd4j-pay-api-domain</module>
│ │ <module>ddd4j-pay-api-infrastructure</module>
│ │ </modules>
│ │
│ ├── ddd4j-pay-api-adapter/ # 支付 API 适配层
│ │ └── src/main/java/io/ddd4j/pay/api/
│ │ └── adapter/
│ │ └── ... # 支付接口 Controller / RPC
│ │
│ ├── ddd4j-pay-api-client/ # 支付 API 客户端 SDK
│ │ └── src/main/java/io/ddd4j/pay/api/
│ │ └── client/
│ │ └── ... # Feign Client / 调用接口
│ │
│ ├── ddd4j-pay-api-app/ # 支付 API 应用层
│ │ └── src/main/java/io/ddd4j/pay/api/
│ │ └── app/
│ │ └── ... # 支付流程编排 / 对账 / 退款
│ │
│ ├── ddd4j-pay-api-domain/ # 支付 API 领域层 ★
│ │ └── src/main/java/io/ddd4j/pay/api/
│ │ └── domain/
│ │ └── ... # Payment / Refund / Transaction
│ │
│ └── ddd4j-pay-api-infrastructure/ # 支付 API 基础设施层
│ └── src/main/java/io/ddd4j/pay/api/
│ └── infrastructure/
│ └── ... # 支付网关接入 / 银行接口 / 证书管理
│
├── ddd4j-pay-admin/ # 支付管理后台域 (Level 2)
│ ├── pom.xml # packaging=pom, modules=5
│ │ <modules>
│ │ <module>ddd4j-pay-admin-adapter</module>
│ │ <module>ddd4j-pay-admin-client</module>
│ │ <module>ddd4j-pay-admin-app</module>
│ │ <module>ddd4j-pay-admin-domain</module>
│ │ <module>ddd4j-pay-admin-infrastructure</module>
│ │ </modules>
│ │
│ ├── ddd4j-pay-admin-adapter/ # Admin 适配层
│ │ └── src/main/java/io/ddd4j/pay/admin/
│ │ └── adapter/
│ │ └── ... # 管理后台 Controller
│ │
│ ├── ddd4j-pay-admin-client/ # Admin 客户端 SDK
│ │ └── src/main/java/io/ddd4j/pay/admin/
│ │ └── client/
│ │ └── ... # Admin 调用接口
│ │
│ ├── ddd4j-pay-admin-app/ # Admin 应用层
│ │ └── src/main/java/io/ddd4j/pay/admin/
│ │ └── app/
│ │ └── ... # 商户管理 / 费率配置 / 风控
│ │
│ ├── ddd4j-pay-admin-domain/ # Admin 领域层 ★
│ │ └── src/main/java/io/ddd4j/pay/admin/
│ │ └── domain/
│ │ └── ... # Merchant / FeeRule / RiskRule
│ │
│ └── ddd4j-pay-admin-infrastructure/ # Admin 基础设施层
│ └── src/main/java/io/ddd4j/pay/admin/
│ └── infrastructure/
│ └── ... # 商户数据持久化 / 风控引擎
│
├── ddd4j-pay-common/ # 公共模块 (Level 2)
│ ├── pom.xml # packaging=pom, modules=2
│ │ <modules>
│ │ <module>ddd4j-pay-common-domain</module>
│ │ <module>ddd4j-pay-common-infrastructure</module>
│ │ </modules>
│ │
│ ├── ddd4j-pay-common-domain/ # 公共领域对象
│ │ └── src/main/java/io/ddd4j/pay/common/
│ │ └── domain/
│ │ └── ... # Money / Currency / PayChannel 枚举
│ │
│ └── ddd4j-pay-common-infrastructure/ # 公共基础设施
│ └── src/main/java/io/ddd4j/pay/common/
│ └── infrastructure/
│ └── ... # 分布式锁 / 幂等组件 / 日志
│
├── libs/ # 本地 jar 依赖 (如银行 SDK)
├── docs/ # 文档
│ └── icons/
└── ...模块完整层级结构
ddd4j-pay (父 POM)
├── Level 2: ddd4j-pay-bom — BOM 版本管理
├── Level 2: ddd4j-pay-dependencies — 外部依赖版本管理
├── Level 2: ddd4j-pay-api — 支付接口域 (5 个 Level 3 子模块)
├── Level 2: ddd4j-pay-admin — 管理后台域 (5 个 Level 3 子模块)
└── Level 2: ddd4j-pay-common — 公共模块 (2 个 Level 3 子模块)
│
┌──────────────────────────────────┘
▼
总计 14 个 Maven 模块 (含 pom 类型)两层业务域:
ddd4j-pay-api:面向 C 端用户/商户的支付接口(下单、支付、退款、查询)ddd4j-pay-admin:面向运营/管理员的后台管理(商户管理、费率配置、风控规则)
各模块的包结构说明
| Level 2 模块 | Level 3 模块 | 包路径 | 职责 |
|---|---|---|---|
pay-bom | — | — | 统一管理 14 个模块版本号 |
pay-dependencies | — | — | 集中管理外部依赖版本 |
pay-api | pay-api-adapter | io.ddd4j.pay.api.adapter | 支付 REST/RPC 接口 |
pay-api | pay-api-client | io.ddd4j.pay.api.client | 支付服务 SDK(给其他系统调用) |
pay-api | pay-api-app | io.ddd4j.pay.api.app | 支付流程编排(下单/退款/对账) |
pay-api | pay-api-domain | io.ddd4j.pay.api.domain | 支付核心领域(Payment/Refund/Transaction) |
pay-api | pay-api-infrastructure | io.ddd4j.pay.api.infrastructure | 支付网关接入/银行接口/证书管理 |
pay-admin | pay-admin-adapter | io.ddd4j.pay.admin.adapter | 管理后台 Controller |
pay-admin | pay-admin-client | io.ddd4j.pay.admin.client | Admin SDK |
pay-admin | pay-admin-app | io.ddd4j.pay.admin.app | 商户管理/费率/风控编排 |
pay-admin | pay-admin-domain | io.ddd4j.pay.admin.domain | 商户/费率/风控领域 |
pay-admin | pay-admin-infrastructure | io.ddd4j.pay.admin.infrastructure | 商户数据/风控引擎实现 |
pay-common | pay-common-domain | io.ddd4j.pay.common.domain | 共享值对象(Money/Currency) |
pay-common | pay-common-infrastructure | io.ddd4j.pay.common.infrastructure | 分布式锁/幂等/日志组件 |
COLA 四层职责分工
| 层 | pay-api 职责 | pay-admin 职责 |
|---|---|---|
| Adapter | 支付下单/退款/查询 REST API | 商户管理/费率配置/风控规则 REST API |
| Application | 支付流程编排(下单→风控→扣款→通知) | 商户入驻/费率变更/风控策略编排 |
| Domain ★ | Payment / Refund / Transaction 核心模型 | Merchant / FeeRule / RiskRule 核心模型 |
| Infrastructure | 银行网关实现 / 支付回调处理 / 证书管理 | 商户数据持久化 / 风控规则引擎 / 审计日志 |
模块间依赖关系图
┌──────────────────────────────────────────────────────────────────┐
│ ddd4j-pay-bom │
│ ddd4j-pay-dependencies │
├──────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────┐ ┌──────────────────────────────┐│
│ │ ddd4j-pay-api │ │ ddd4j-pay-admin ││
│ │ │ │ ││
│ │ api-adapter │ │ admin-adapter ││
│ │ ↓ │ │ ↓ ││
│ │ api-app ──→ api-domain ★ │ │ admin-app ──→ admin-domain ★││
│ │ ↓ ↑ │ │ ↓ ↑ ││
│ │ api-infrastructure ────┘ │ │ admin-infrastructure ───┘ ││
│ │ ↓ │ │ ↓ ││
│ │ api-client │ │ admin-client ││
│ └─────────┬───────────────────┘ └─────────┬────────────────────┘│
│ │ │ │
│ │ ┌──────────┐ │ │
│ └──────────→ common ←──────────┘ │
│ │ │ │
│ │ common- │ │
│ │ domain │ │
│ │ ↓ │ │
│ │ common- │ │
│ │ infra │ │
│ └──────────┘ │
│ │
│ 关键依赖: │
│ • api-domain ──→ common-domain (共享值对象) │
│ • admin-domain ──→ common-domain (共享值对象) │
│ • api-infrastructure ──→ common-infrastructure (共享组件) │
│ • admin-infrastructure ──→ common-infrastructure (共享组件) │
│ • api-app ──→ admin-client (调用管理后台服务) │
└──────────────────────────────────────────────────────────────────┘跨域依赖规则:
pay-api和pay-admin是两个独立的 Bounded Context- 它们通过
common-*共享值对象和基础设施 - 两个域的应用层可以通过各自的
client模块相互调用 - 严禁
pay-api-domain直接依赖pay-admin-domain(跨域聚合隔离) - 严禁 通过数据库层面实现跨域数据访问(各自独立表空间)
适用场景
- 大型支付/金融系统,需要严格的域隔离
- 多业务域共存(如支付接口 + 管理后台 + 对账 + 风控)
- 团队 15-50 人,按业务域分小组
- 需要 Bounded Context 级别的模块隔离
- 需要独立发布 Client SDK 给多个下游系统
- 对代码质量和架构一致性有极高要求
与 ddd4j-rednote 的结构对比
| 维度 | ddd4j-rednote (简单) | ddd4j-pay (复杂) |
|---|---|---|
| Level 2 业务域数 | 1 (api) | 2 (api + admin) |
| Level 3 子模块数 | 7 | 12 |
| 总模块数 | 10 | 14 |
| 跨域依赖 | 无 | 通过 client 相互调用 |
| Common 共享范围 | 单域内共享 | 跨域共享 |
| BOM 管理复杂度 | 低 | 中 |
| 适用团队规模 | 5-15 人 | 15-50 人 |
优点
- 编译时强约束:
pay-api-domain和pay-admin-domain完全隔离 - 每个业务域可独立发布 Client SDK
- Common 模块按 Domain/Infrastructure 分层,避免成为"大垃圾桶"
- BOM + Dependencies 统一 14 个模块的版本,避免依赖地狱
- 高粒度模块可独立测试、独立编译
- 为大团队并行开发提供清晰的模块边界
缺点
- 14 个 Maven 模块维护成本高
- 新人学习曲线陡峭(需要理解 API/Admin 两个域的边界)
- Client 模块的接口变化需要协调多个服务同时升级
- BOM 版本发布需要严格的版本管理流程
- 构建时间较长(14 个模块需要全部编译)
- 模块间过度拆分可能导致过早抽象
Architecture Patterns Reference
This document provides detailed structure examples for four DDD architecture patterns.
1. DDD Classic Layered Architecture (DDD 经典分层架构)
Layer Structure
interfaces (接口层)
↓ 依赖
application (应用层)
↓ 依赖
domain (领域层)
↑ 实现接口
infrastructure (基础设施层)Package Structure
{basePackage}.{module}.interfaces
{basePackage}.{module}.application
{basePackage}.{module}.domain
{basePackage}.{module}.infrastructureKey Components
- interfaces: Controllers, DTOs, Filters, Exception Handlers
- application: Application Services, Commands, Queries, Event Handlers
- domain: Aggregates, Entities, Value Objects, Domain Services, Repository Interfaces
- infrastructure: Repository Implementations, External Services, Configurations
Reference
See: docs/1、DDD 经典分层架构目录结构.md
2. Hexagonal Architecture (六边形架构)
Layer Structure
adapter (适配器层)
↓ 依赖
application (应用层)
↓ 依赖
domain (领域层)
↑ 实现接口
infrastructure (基础设施层)Package Structure
{basePackage}.{module}.adapter
{basePackage}.{module}.application
{basePackage}.{module}.domain
{basePackage}.{module}.infrastructureKey Components
- adapter: Web Controllers, RPC Providers, Message Consumers, Scheduled Jobs
- application: Use Cases, Application Services, Ports (Inbound/Outbound)
- domain: Entities, Value Objects, Domain Services, Domain Events
- infrastructure: Repository Implementations, External Service Adapters, Configurations
Ports and Adapters
- Inbound Ports: Define application services (e.g.,
IOrderService) - Outbound Ports: Define external dependencies (e.g.,
IOrderRepository,IPaymentProvider) - Inbound Adapters: Web Controllers, CLI, Message Consumers
- Outbound Adapters: Database Repositories, External API Clients, Message Publishers
Reference
See: docs/2、六边形架构详细目录结构参考.md
3. Clean Architecture (整洁架构)
Layer Structure
interfaces (接口适配器层)
↓ 依赖
application (应用层/用例层)
↓ 依赖
domain (领域层/实体层)
↑ 实现接口
infrastructure (基础设施层)Package Structure
{basePackage}.{module}.interfaces
{basePackage}.{module}.application
{basePackage}.{module}.domain
{basePackage}.{module}.infrastructureKey Components
- interfaces: Controllers, Presenters, Gateways (Input/Output Ports)
- application: Use Cases, Application Services, Input/Output Ports
- domain: Entities, Value Objects, Domain Services, Repository Interfaces
- infrastructure: Repository Implementations, External Service Adapters, Configurations
Ports
- Input Ports: Define use case interfaces
- Output Ports: Define external dependencies (Repository, External Services)
Reference
See: docs/3、整洁架构详细目录结构参考.md
4. COLA V5 (菱形架构)
Layer Structure
adapter (适配器层)
↓ 依赖
app (应用层)
↓ 依赖
domain (领域层)
↑ 实现接口
infrastructure (基础设施层)Package Structure
{basePackage}.{module}.adapter
{basePackage}.{module}.app
{basePackage}.{module}.domain
{basePackage}.{module}.infrastructureKey Components
- adapter: Web Controllers, RPC Providers, Job Schedulers, Message Listeners
- app: Executors (Command/Query), Application Services, Extensions
- domain: Entities, Value Objects, Domain Services, Abilities, Gateways, Repository Interfaces
- infrastructure: Repository Implementations, Gateway Implementations, External Clients
COLA V5 Specific Features
- Executors: Command Executors (
CmdExe) and Query Executors (QryExe) - Extensions: Extension Points for business logic extension
- Abilities: Domain abilities for cross-entity business rules
- Gateways: Domain gateways for external dependencies
Reference
See: docs/4、COLA V5 架构详细目录结构参考.md
Comparison Table
| Aspect | DDD Classic | Hexagonal | Clean | COLA V5 |
|---|---|---|---|---|
| Interface Layer | interfaces | adapter | interfaces | adapter |
| Application Layer | application | application | application | app |
| Domain Layer | domain | domain | domain | domain |
| Infrastructure | infrastructure | infrastructure | infrastructure | infrastructure |
| Port Concept | No | Yes (Inbound/Outbound) | Yes (Input/Output) | Yes (Gateways) |
| Use Cases | Application Services | Use Cases | Use Cases | Executors |
| Extension | No | No | No | Yes (Extension Points) |
| Ability | Domain Services | Domain Services | Domain Services | Abilities |
Choosing an Architecture
Choose DDD Classic when:
- Following Eric Evans' DDD book
- Need clear layer separation
- Standard DDD implementation
Choose Hexagonal when:
- Need technology isolation
- Multiple driving adapters (Web, CLI, Message)
- High testability requirements
Choose Clean Architecture when:
- Need concentric circle structure
- High testability requirements
- Business logic complexity
Choose COLA V5 when:
- Need extension mechanism
- Want ability pattern
- Alibaba COLA framework users
Common Principles
All four architectures follow these principles:
1. Dependency Rule: Dependencies point inward, domain layer has no external dependencies 2. Interface Segregation: Domain layer defines interfaces, infrastructure implements them 3. Separation of Concerns: Clear layer responsibilities 4. Testability: Domain layer can be tested independently
COLA v5 菱形架构核心原理
菱形架构全景
COLA v5(Clean Object-oriented Layered Architecture)采用"菱形架构"——以 Domain 为中心,Adapter 和 Infrastructure 分居两侧:
┌──────────────┐
│ Adapter │ ← 适配层:HTTP、MQ、RPC 协议适配
└──────┬───────┘
│
┌──────▼───────┐
│ Application│ ← 应用层:编排、事务、CQRS 分流
┌───────┴───────┬───────┴───────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Domain │ │ Domain │ │ Domain │ ← 领域层:核心业务逻辑 ★
│ ★ │ │ ★ │ │ ★ │
└──────────┘ └──────────┘ └──────────┘
▲ ▲ ▲
└───────────────┴───────────────┘
│
┌──────▼───────┐
│Infrastructure│ ← 基础设施层:DB、MQ、缓存、外部 API
└──────────────┘四层职责
| 层 | 模块名 | 核心职责 | 依赖方向 |
|---|---|---|---|
| Adapter | {project}-adapter | HTTP/RPC/MQ 协议适配,DTO 转换 | → app, domain |
| Application | {project}-app | 用例编排,事务管理,CQRS 执行器 | → domain, infrastructure |
| Domain | {project}-domain | 领域模型、业务规则、Repository/Gateway 接口 | 无(零依赖) |
| Infrastructure | {project}-infrastructure | 技术实现(DB/MQ/缓存)、Repository/Gateway 实现 | → domain |
四大核心约束(P0)
1. Domain 零依赖 — Domain 层不允许 import Spring/JPA/MyBatis 等框架注解 2. App 层无业务逻辑 — App 层仅编排,不放 if/else 业务判断 3. Adapter 层无 SQL/业务 — Adapter 只做协议转换和数据映射 4. 模块间无循环依赖 — 四层之间只允许单向依赖
依赖方向规则
adapter → app → domain ← infrastructure
↑
domain 不依赖任何人v5 新增概念
- Extension Point(扩展点):通过
@ExtensionPoint+@Extension(bizId = "...")实现业务维度的扩展 - Ability(领域能力):
domain/ability/为领域层提供能力抽象 - 组件化基础设施:分布式锁、限流器、熔断器作为基础设施组件
- CQRS 强化:
app/executor/command/和app/executor/query/严格分离
COLA v5 项目脚手架
Maven Archetype 快速创建
mvn archetype:generate \
-DarchetypeGroupId=com.alibaba.cola \
-DarchetypeArtifactId=cola-archetype-web \
-DarchetypeVersion=5.0.0 \
-DgroupId=com.yourcompany \
-DartifactId=your-project \
-Dversion=1.0.0-SNAPSHOT手动搭建(推荐生产使用)
多模块 Maven 配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.yourcompany</groupId>
<artifactId>your-project</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>start</module>
<module>adapter</module>
<module>app</module>
<module>domain</module>
<module>infrastructure</module>
<module>common</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.0</version>
</parent>
<properties>
<java.version>17</java.version>
<cola.version>5.0.0</cola.version>
<mybatis.version>3.0.3</mybatis.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.alibaba.cola</groupId>
<artifactId>cola-component-dto</artifactId>
<version>${cola.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cola</groupId>
<artifactId>cola-component-domain-starter</artifactId>
<version>${cola.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.cola</groupId>
<artifactId>cola-component-catchlog-starter</artifactId>
<version>${cola.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>各模块依赖
| 模块 | 依赖 | 说明 |
|---|---|---|
| start | adapter, common | 启动模块,依赖所有非 domain 模块 |
| adapter | app, domain | 适配层,可调用应用层和领域层 |
| app | domain, infrastructure | 应用层,编排领域层 + 基础设施 |
| domain | (none) | 领域层,纯 POJO,零框架依赖 |
| infrastructure | domain | 基础设施实现领域层接口 |
| common | (none) | 通用工具和常量 |
Gradle 版本
// settings.gradle
rootProject.name = 'your-project'
include 'start', 'adapter', 'app', 'domain', 'infrastructure', 'common'
// build.gradle (根)
subprojects {
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
group = 'com.yourcompany'
version = '1.0.0-SNAPSHOT'
sourceCompatibility = '17'
}启动模块 (start)
@SpringBootApplication(scanBasePackages = "com.yourcompany")
@EnableCola
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}@EnableCola 是 COLA v5 新增注解,启动 COLA 扩展点机制和领域事件总线。