news 2026/4/29 4:27:44

别再写Service地狱了!用DDD重构我的项目(4)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
别再写Service地狱了!用DDD重构我的项目(4)

事件,触发异步消息

在领域驱动设计( DDD)中,领域事件(Domain Events)是一种模型,用于表示领域中发生的有意义的事件。这些事件对业务来说是重要的,并且通常表示领域状态的变化。适配器(Adapter)在这个上下文中扮演着将领域事件与系统其他部分或外部系统连接起来的角色。

概念

领域事件是DDD中的一个关键概念,它代表了领域中发生的一个具有业务意义的事件。这些事件通常是由领域实体或聚合根的状态变化触发的。领域事件不仅仅是数据的变化,它们还承载了业务上下文和业务意图。

特性

  1. 意义明确:领域事件通常具有明确的业务含义,例如“用户已下单”、“商品已支付”等。
  2. 不可变性:一旦领域事件被创建,它的状态就不应该被改变。这有助于确保事件的一致性和可靠性。
  3. 时间相关性:领域事件通常包含事件发生的时间戳,这有助于追踪事件的顺序和时间线。
  4. 关联性:领域事件可能与特定的领域实体或聚合根相关联,这有助于完成事件的上下文。
  5. 可观察性:领域事件可以被其他部分的系统监听和响应,有助于实现系统间的解耦。

用途

  1. 解耦:领域事件可以帮助系统内部或系统间的不同部分解耦,因为它们提供了一种基于事件的通信机制。
  2. 业务逻辑触发:领域事件可以触发其他业务逻辑的执行,例如推送消息(优惠券到账)、更新其他聚合或生成数据流式报告等。
  3. 事件溯源:领域事件可以用于实现事件溯源(Event Sourcing),这是一种存储系统状态变化的方法,通过重放事件来恢复系统状态。
  4. 集成:领域事件可以用于系统与外部系统的集成,通过发布事件来通知外部系统领域中发生的变化。

实现

5.1 领域层

  1. 定义事件接口:创建一个或多个接口来定义领域事件的结构和行为。
  2. 创建领域事件类:基于定义的接口,实现具体的领域事件类,包含必要的属性和方法。
  3. 触发领域事件:在领域逻辑中的适当位置,实例化并发布领域事件。

5.2 基础层

  • 实现领域接口:使用消息队列(如RocketMQ或RabbitMQ)来实现领域事件的发布和订阅机制。

5.3 触发器层/接口层

  • 监听领域事件消息:在系统的其他部分或外部系统中,监听领域事件并根据事件来执行相应的业务逻辑或集成逻辑。

案例

以下是一个简单的Java事件消息场景案例代码,展示了如何在DDD架构中定义领域事件、发布事件以及如何通过适配器模式将事件传递给外部系统或服务。

首先,我们定义一个领域事件接口和一个具体的领域事件类:

public interface DomainEvent { Date occurredOn(); } public class OrderCreatedEvent implements DomainEvent { private final String orderId; private final Date occurredOn; public OrderCreatedEvent(String orderId) { this.orderId = orderId; this.occurredOn = new Date(); } @Override public Date occurredOn() { return this.occurredOn; } public String getOrderId() { return orderId; } }

接下来,我们创建一个事件发布器接口和一个基于消息队列的实现:

public interface DomainEventPublisher { void publish(DomainEvent event); } public class MessageQueueEventPublisher implements DomainEventPublisher { // 模拟消息队列客户端 private final MessageQueueClient messageQueueClient; public MessageQueueEventPublisher(MessageQueueClient messageQueueClient) { this.messageQueueClient = messageQueueClient; } @Override public void publish(DomainEvent event) { // 将领域事件转换为消息并发送到消息队列 messageQueueClient.send(serialize(event)); } private String serialize(DomainEvent event) { // 序列化事件对象为JSON或其他格式 // 这里简化为直接使用toString() return event.toString(); } } public class MessageQueueClient { public void send(String message) { // 实际的消息发送逻辑 System.out.println("Message sent to queue: " + message); } }

现在,我们可以在领域逻辑中触发领域事件:

public class OrderService { private final DomainEventPublisher eventPublisher; public OrderService(DomainEventPublisher eventPublisher) { this.eventPublisher = eventPublisher; } public void createOrder(String orderId) { // 创建订单的业务逻辑... // 创建并发布订单创建事件 OrderCreatedEvent event = new OrderCreatedEvent(orderId); eventPublisher.publish(event); } }

最后,我们模拟一个外部系统的适配器,它监听消息队列中的事件消息:

public class ExternalSystemAdapter { private final MessageQueueClient messageQueueClient; public ExternalSystemAdapter(MessageQueueClient messageQueueClient) { this.messageQueueClient = messageQueueClient; // 假设这里有一个方法来监听消息队列 messageQueueClient.onMessage(this::onEventReceived); } private void onEventReceived(String message) { // 处理接收到的事件消息 System.out.println("External system received event: " + message); // 根据事件类型执行相应的逻辑 } }

最终,我们可以在应用程序中初始化这些组件并执行业务逻辑:

public class Application { public static void main(String[] args) { MessageQueueClient messageQueueClient = new MessageQueueClient(); DomainEventPublisher eventPublisher = new MessageQueueEventPublisher(messageQueueClient); OrderService orderService = new OrderService(eventPublisher); // 初始化外部系统适配器 ExternalSystemAdapter externalSystemAdapter = new ExternalSystemAdapter(messageQueueClient); // 执行业务逻辑,创建订单 orderService.createOrder("XFG1000900111199"); } }

在这个例子中,当OrderService创建一个新订单时,它会发布一个OrderCreatedEvent。MessageQueueEventPublisher接收到这个事件,并将其发送到消息队列。ExternalSystemAdapter监听消息队列,并在接收到事件消息时执行相应的逻辑。

请注意,这个例子是为了演示目的而简化的。在实际应用中,你需要处理消息队列的连接、错误处理、事件的序列化和反序列化等复杂问题。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/29 4:26:43

from-python-to-numpy实战:从随机游走看向量化威力

from-python-to-numpy实战:从随机游走看向量化威力 【免费下载链接】from-python-to-numpy An open-access book on numpy vectorization techniques, Nicolas P. Rougier, 2017 项目地址: https://gitcode.com/gh_mirrors/fr/from-python-to-numpy 在数据科…

作者头像 李华
网站建设 2026/4/29 4:22:33

Zeego性能优化秘籍:提升React Native应用菜单体验的7个技巧

Zeego性能优化秘籍:提升React Native应用菜单体验的7个技巧 【免费下载链接】zeego Menus for React (Native) done right. 项目地址: https://gitcode.com/gh_mirrors/ze/zeego Zeego作为React Native应用的专业菜单解决方案,其性能表现直接影响…

作者头像 李华
网站建设 2026/4/29 4:19:55

vue-beauty自定义组件开发教程:扩展你的组件库

vue-beauty自定义组件开发教程:扩展你的组件库 【免费下载链接】vue-beauty Beautiful UI components build with vue and ant design 项目地址: https://gitcode.com/gh_mirrors/vu/vue-beauty vue-beauty是一个基于Vue和Ant Design构建的UI组件库&#xff…

作者头像 李华
网站建设 2026/4/29 4:19:13

MutComputeX安装和使用教程

MutComputeX 是一个强大的基于 3D 深度学习的蛋白质工程工具,能够预测蛋白质-配体界面的突变。然而,官方文档主要针对 AMD 显卡(ROCm平台)进行了配置,对于使用普通 NVIDIA 显卡或仅使用 CPU 的用户来说,直接…

作者头像 李华
网站建设 2026/4/29 4:19:10

PyTorch 2.8镜像开发者案例:用该镜像完成NeRF-Wild野外场景重建项目

PyTorch 2.8镜像开发者案例:用该镜像完成NeRF-Wild野外场景重建项目 1. 项目背景与镜像优势 NeRF-Wild是一种用于野外场景三维重建的先进神经网络渲染技术,它对计算资源有着极高的要求。传统的本地开发环境往往难以满足其复杂的依赖关系和计算需求&…

作者头像 李华