为什么需要 EventSourcingHandler(在聚合对象中)?

Jon*_*n M 1 java axon

公平警告:我不知道我在做什么,所以即使问这个问题也可能出错。

我想更新一个简单对象(聚合)的状态,然后为 UI 提供更改对象的投影。这是我的聚合对象(命令处理程序存在,但未在此处显示)。

@Aggregate
public class Widget {
    @AggregateIdentifier
    private String id;
    private String color;
...
    @EventSourcingHandler
    public void on(ChangeColorEvt evt) {
        color = evt.getColor();
    }
... 
}
Run Code Online (Sandbox Code Playgroud)

...这是我的预测:

public class WidgetProjection {
    private final EntityManager entityManager;
    private final QueryUpdateEmitter queryUpdateEmitter;
...
    @EventHandler
    public void on(ChangeColorEvt evt) {
        ProjectedWidget projection = entityManager.find(ProjectedWidget.class, evt.getId());
        projection.setColor(evt.getColor());
        queryUpdateEmitter.emit(FetchWidget.class, query -> evt.getId().startsWith(query.getFilter().getIdStartsWith()), projection);
    }
...
}
Run Code Online (Sandbox Code Playgroud)

QueryHandler 做你所期望的,找到实例并返回它。

所以这里是我的问题:

  1. 为什么我需要聚合中的 EventSourcingHandler?也就是说,它似乎可以工作,但结果并未存储或发送到任何地方。
  2. 所以,这成为我的下一个问题:在执行 EventSourcing Handler 之后,Widget 的结果实例(不是投影)是否存储、查看或发送到任何地方?
  3. 如果确实需要 EventSourcingHandler,有没有办法避免我的业务逻辑的两个独立副本(一个在 EventSourcingHandler 中,一个在 EventHandler 中)?我真的很讨厌必须在两个地方更新相同的业务逻辑的想法。

我很感激该小组可以提供的任何清晰度。谢谢你的帮助!

Ste*_*ven 5

我希望我能帮助你解决这个问题!

简短的回答是:使用 的必要性@EventSourcingHandler实际上取决于您希望如何为您的应用程序建模。

现在,这并没有说太多,所以让我详细说明一下为什么我要说明这一点。在回答您的问题时,我假设您希望创建一个应用程序,您可以在其中遵循 DDD、CQRS 和事件溯源的思想。因此,Axon 在构建应用程序时试图为您简化的概念。

让我从这里回顾你的编号问题:

  1. @EventSourcingHandler在聚合中需要带注释的函数的原因是 (1) 根据发布的 (2) 事件更新聚合状态。转到第 1 点,为什么要更新聚合的状态?由于您的聚合是应用程序的命令模型,因此它的任务是根据收到的命令做出决策。为了能够做出决定,有时聚合需要状态,但有时不需要。所以在Widget你分享例子中,我假设color字段根本不用于稍后驱动业务逻辑,因此您可以完全从聚合中省略此状态而不会出现任何问题。在我的第二点回应中,我试图指出聚合只会处理源自自身的事件。这是因为事件是您的聚合的来源,因为事件构成了在该给定模型上发生的所有增量。
  2. 您的以下问题非常适合继续我在第 1 点开始的解释。答案很简单,您的WidgetAggregate 未存储在任何地方,而不是按原样存储。每次您从 axon 中检索您的聚合时Repository(这在 Axon 中为您自动完成),默认为EventSourcingRepository在 Axon 中,该给定聚合的所有事件都将从事件存储中检索。比,一个聚合实例被创建,框架将重放它为该精确聚合实例找到的所有事件。因此,每次输入新命令时,您都可以有效地对聚合进行事件溯源。这听起来有点矫枉过正,因为给定聚合的事件数量可能会增长到相当大的集合。这可以通过做一些事情来解决,比如制作聚合的快照
  3. 如果将应用程序拆分为处理业务逻辑的专用部分、命令模型和仅返回查询模型作为答案的部分(查询模型),那么您可以决定使用State Stored Aggregate。所以请注意,在使用 Axon 时,您根本不需要进行事件溯源;它只是框架的默认操作方式。因此,我理解您的担忧,即您正在复制您的逻辑。但是,您可以严格地将做出所有决定的部分分开存放在您的聚合中。查询模型(在您的示例中ProjectedWidget)可以存储在您想要的任何格式和任何数据库/工具中,理想情况下没有任何业务逻辑。如果您发现自己在应用程序的查询端添加了业务逻辑,这可能建议您将此位升级为源自聚合的事件。

我希望这能让您了解为什么要开始使用 Event Sourcing。这篇文章比我在这里做的更详细地描述了CQRS,还有这个关于事件溯源的链接;希望它们可以作为比我刚刚给你的更彻底的解释。