
Java 架构师的核心能力,不是堆砌框架,而是在业务、成本、团队、合规的约束下做技术权衡。一个系统能不能上线、能不能演进,取决于架构师是否定义了清晰的边界和可替换的依赖。
下面以高并发订单系统为例,从需求分析到代码落地,展示 Java 架构师的完整决策过程。
业务需求:
关键约束:高并发、变化快、团队有限。架构目标不是"大而全",而是分层清晰、依赖倒置、读写分离、可观测。
ADR-001:采用分层架构 + 依赖倒置
状态:已接受
背景:业务变化快,需替换支付渠道和存储
决策:领域层定义接口,基础设施层实现
后果:增加少量接口代码,换取可测试性和可替换性
ADR-002:CQRS 读写分离
状态:已接受
背景:下单写入和订单查询压力差异大
决策:写模型走领域层,读模型走独立查询服务
后果:增加最终一致性复杂度,换取查询性能
ADR-003:领域事件 + 消息队列
状态:已接受
背景:支付成功后需通知库存、积分、通知服务
决策:发布领域事件,异步解耦
后果:需处理消息幂等和顺序四层结构:接口层、应用层、领域层、基础设施层。依赖方向永远指向内层。
package domain;
import java.math.BigDecimal;
import java.time.Instant;
import java.util.List;
public class Order {
private final String id;
private final String userId;
private OrderStatus status;
private final List<OrderItem> items;
private final Instant createdAt;
public Order(String id, String userId, List<OrderItem> items) {
if (items == null || items.isEmpty()) {
throw new IllegalArgumentException("items required");
}
this.id = id;
this.userId = userId;
this.items = List.copyOf(items);
this.status = OrderStatus.CREATED;
this.createdAt = Instant.now();
}
public void pay() {
if (status != OrderStatus.CREATED) {
throw new IllegalStateException("only CREATED can pay");
}
this.status = OrderStatus.PAID;
}
public void cancel() {
if (status == OrderStatus.PAID) {
throw new IllegalStateException("PAID cannot cancel directly");
}
this.status = OrderStatus.CANCELLED;
}
public BigDecimal total() {
return items.stream()
.map(OrderItem::subtotal)
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
public String id() { return id; }
public String userId() { return userId; }
public OrderStatus status() { return status; }
public List<OrderItem> items() { return items; }
}package domain;
public interface OrderRepository {
void save(Order order);
Order findById(String id);
}
public interface PaymentGateway {
PaymentResult pay(String orderId, BigDecimal amount);
}
public interface DomainEventPublisher {
void publish(Object event);
}领域层只定义"做什么",不关心"怎么做"。
package application;
import domain.*;
import org.springframework.transaction.annotation.Transactional;
public class OrderApplicationService {
private final OrderRepository repository;
private final PaymentGateway paymentGateway;
private final DomainEventPublisher publisher;
public OrderApplicationService(OrderRepository repository,
PaymentGateway paymentGateway,
DomainEventPublisher publisher) {
this.repository = repository;
this.paymentGateway = paymentGateway;
this.publisher = publisher;
}
@Transactional
public void pay(String orderId) {
Order order = repository.findById(orderId);
PaymentResult result = paymentGateway.pay(orderId, order.total());
if (!result.success()) {
throw new PaymentFailedException(result.message());
}
order.pay();
repository.save(order);
publisher.publish(new OrderPaidEvent(orderId, order.userId()));
}
}应用层负责事务边界和用例编排,业务规则留在领域层。
package infrastructure;
import domain.*;
import org.springframework.stereotype.Repository;
@Repository
public class JdbcOrderRepository implements OrderRepository {
private final OrderJdbcMapper mapper;
public JdbcOrderRepository(OrderJdbcMapper mapper) {
this.mapper = mapper;
}
@Override
public void save(Order order) {
mapper.insert(order);
}
@Override
public Order findById(String id) {
OrderDO data = mapper.selectById(id);
return OrderConverter.toDomain(data);
}
}替换存储或支付渠道时,只新增实现类,领域层和应用层不变。
Java 21 虚拟线程适合 IO 密集型场景,无需线程池调优:
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class OrderQueryService {
private final Semaphore limit = new Semaphore(200);
public String query(String orderId) throws InterruptedException {
limit.acquire();
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
return executor.submit(() -> remoteQuery(orderId)).get();
} finally {
limit.release();
}
}
private String remoteQuery(String orderId) throws InterruptedException {
Thread.sleep(50);
return "order:" + orderId;
}
}虚拟线程不等于无限并发,下游容量有限时仍需 Semaphore 限流。
下单接口必须幂等,避免重复扣款:
public class IdempotentGuard {
private final StringRedisTemplate redis;
public IdempotentGuard(StringRedisTemplate redis) {
this.redis = redis;
}
public boolean tryAcquire(String key, long ttlSeconds) {
Boolean ok = redis.opsForValue()
.setIfAbsent(key, "1", Duration.ofSeconds(ttlSeconds));
return Boolean.TRUE.equals(ok);
}
}领域事件消费端必须幂等:
public void onOrderPaid(OrderPaidEvent event) {
String key = "evt:order_paid:" + event.orderId();
if (!idempotentGuard.tryAcquire(key, 86400)) {
return;
}
// 处理库存、积分、通知
}演进路径:订单量再增大时,可引入分库分表、CQRS 读模型独立部署、事件溯源。这些演进不推翻现有分层。
Java 架构师的价值,不在于用了多少框架,而在于把复杂系统拆成可理解、可测试、可替换的模块。分层 + 依赖倒置 + 领域事件 + 幂等设计,让订单系统在高并发下稳定运行,也为未来演进留出空间。架构的价值,在于让变化发生时,代价可控。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。