hexagonal-architecture-layers-java
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseWhen to Use
适用场景
Load this skill when:
- Designing a new Java service with clean, testable layers
- Refactoring Spring code to isolate the domain from frameworks
- Supporting multiple adapters (REST + messaging, JPA + Mongo)
- Enforcing dependency direction and clear module boundaries
在以下场景中使用本技能:
- 设计具有清晰、可测试分层的全新Java服务
- 重构Spring代码以将领域层与框架解耦
- 支持多种适配器(REST + 消息服务、JPA + Mongo)
- 强制依赖方向与明确的模块边界
Critical Patterns
核心模式
Pattern 1: Domain is pure
模式1:领域层保持纯净
Domain has no framework annotations, no persistence concerns, and no I/O.
领域层不包含框架注解,不处理持久化相关逻辑,也不涉及I/O操作。
Pattern 2: Application orchestrates
模式2:应用层负责编排
Application defines use cases and ports, calling domain logic and delegating I/O to ports.
应用层定义用例与端口,调用领域层逻辑并将I/O操作委托给端口。
Pattern 3: Infrastructure adapts
模式3:基础设施层负责适配
Infrastructure implements ports and wires adapters (controllers, repositories, clients).
基础设施层实现端口,并连接适配器(控制器、仓库、客户端)。
Code Examples
代码示例
Example 1: Domain model + output port
示例1:领域模型 + 输出端口
java
package com.acme.order.domain;
public record OrderId(String value) { }
public final class Order {
private final OrderId id;
private final Money total;
public Order(OrderId id, Money total) {
this.id = id;
this.total = total;
}
public OrderId id() { return id; }
public Money total() { return total; }
}java
package com.acme.order.application.port;
import com.acme.order.domain.Order;
import com.acme.order.domain.OrderId;
public interface OrderRepositoryPort {
OrderId nextId();
void save(Order order);
}java
package com.acme.order.domain;
public record OrderId(String value) { }
public final class Order {
private final OrderId id;
private final Money total;
public Order(OrderId id, Money total) {
this.id = id;
this.total = total;
}
public OrderId id() { return id; }
public Money total() { return total; }
}java
package com.acme.order.application.port;
import com.acme.order.domain.Order;
import com.acme.order.domain.OrderId;
public interface OrderRepositoryPort {
OrderId nextId();
void save(Order order);
}Example 2: Application use case + input port
示例2:应用层用例 + 输入端口
java
package com.acme.order.application.usecase;
import com.acme.order.application.port.OrderRepositoryPort;
import com.acme.order.domain.Order;
import com.acme.order.domain.OrderId;
import com.acme.order.domain.Money;
public interface PlaceOrderUseCase {
OrderId place(Money total);
}
public final class PlaceOrderService implements PlaceOrderUseCase {
private final OrderRepositoryPort repository;
public PlaceOrderService(OrderRepositoryPort repository) {
this.repository = repository;
}
@Override
public OrderId place(Money total) {
OrderId id = repository.nextId();
Order order = new Order(id, total);
repository.save(order);
return id;
}
}java
package com.acme.order.application.usecase;
import com.acme.order.application.port.OrderRepositoryPort;
import com.acme.order.domain.Order;
import com.acme.order.domain.OrderId;
import com.acme.order.domain.Money;
public interface PlaceOrderUseCase {
OrderId place(Money total);
}
public final class PlaceOrderService implements PlaceOrderUseCase {
private final OrderRepositoryPort repository;
public PlaceOrderService(OrderRepositoryPort repository) {
this.repository = repository;
}
@Override
public OrderId place(Money total) {
OrderId id = repository.nextId();
Order order = new Order(id, total);
repository.save(order);
return id;
}
}Example 3: Infrastructure adapter + wiring
示例3:基础设施层适配器 + 连接配置
java
package com.acme.order.infrastructure.persistence;
import com.acme.order.application.port.OrderRepositoryPort;
import com.acme.order.domain.Order;
import com.acme.order.domain.OrderId;
import org.springframework.stereotype.Repository;
@Repository
public final class OrderJpaAdapter implements OrderRepositoryPort {
private final SpringOrderRepository repository;
private final OrderMapper mapper;
public OrderJpaAdapter(SpringOrderRepository repository, OrderMapper mapper) {
this.repository = repository;
this.mapper = mapper;
}
@Override
public OrderId nextId() {
return new OrderId(java.util.UUID.randomUUID().toString());
}
@Override
public void save(Order order) {
repository.save(mapper.toEntity(order));
}
}java
package com.acme.order.infrastructure.persistence;
import com.acme.order.application.port.OrderRepositoryPort;
import com.acme.order.domain.Order;
import com.acme.order.domain.OrderId;
import org.springframework.stereotype.Repository;
@Repository
public final class OrderJpaAdapter implements OrderRepositoryPort {
private final SpringOrderRepository repository;
private final OrderMapper mapper;
public OrderJpaAdapter(SpringOrderRepository repository, OrderMapper mapper) {
this.repository = repository;
this.mapper = mapper;
}
@Override
public OrderId nextId() {
return new OrderId(java.util.UUID.randomUUID().toString());
}
@Override
public void save(Order order) {
repository.save(mapper.toEntity(order));
}
}Anti-Patterns
反模式
Don't: Put framework annotations in domain
不要:在领域层中添加框架注解
java
// BAD: domain tied to JPA
@jakarta.persistence.Entity
public class Order {
@jakarta.persistence.Id
private String id;
}java
// 错误示例:领域层与JPA绑定
@jakarta.persistence.Entity
public class Order {
@jakarta.persistence.Id
private String id;
}Don't: Call infrastructure directly from domain
不要:从领域层直接调用基础设施层
java
// BAD: domain depends on Spring repository
public class Order {
private final SpringOrderRepository repository;
}java
// 错误示例:领域层依赖Spring仓库
public class Order {
private final SpringOrderRepository repository;
}Quick Reference
速查表
| Task | Pattern |
|---|---|
| Persist domain data | Define output port in application, implement in infrastructure |
| Expose use case | Define input port and service in application |
| Keep domain pure | No annotations, no I/O, no framework imports |
| 任务 | 模式 |
|---|---|
| 持久化领域数据 | 在应用层定义输出端口,在基础设施层实现 |
| 暴露用例 | 在应用层定义输入端口与服务 |
| 保持领域层纯净 | 无注解、无I/O、无框架导入 |
Resources
参考资源
- Hexagonal Architecture: https://alistair.cockburn.us/hexagonal-architecture/
- Clean Architecture: https://www.oreilly.com/library/view/clean-architecture/9780134494272/
- Hexagonal Architecture: https://alistair.cockburn.us/hexagonal-architecture/
- Clean Architecture: https://www.oreilly.com/library/view/clean-architecture/9780134494272/