公平警告:我不知道我在做什么,所以即使问这个问题也可能出错。
我想更新一个简单对象(聚合)的状态,然后为 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 做你所期望的,找到实例并返回它。
所以这里是我的问题:
我很感激该小组可以提供的任何清晰度。谢谢你的帮助!
我希望我能帮助你解决这个问题!
简短的回答是:使用 的必要性@EventSourcingHandler实际上取决于您希望如何为您的应用程序建模。
现在,这并没有说太多,所以让我详细说明一下为什么我要说明这一点。在回答您的问题时,我假设您希望创建一个应用程序,您可以在其中遵循 DDD、CQRS 和事件溯源的思想。因此,Axon 在构建应用程序时试图为您简化的概念。
让我从这里回顾你的编号问题:
@EventSourcingHandler在聚合中需要带注释的函数的原因是 (1) 根据它发布的 (2) 事件更新聚合状态。转到第 1 点,为什么要更新聚合的状态?由于您的聚合是应用程序的命令模型,因此它的任务是根据收到的命令做出决策。为了能够做出决定,有时聚合需要状态,但有时不需要。所以在Widget你分享例子中,我假设color字段根本不用于稍后驱动业务逻辑,因此您可以完全从聚合中省略此状态而不会出现任何问题。在我的第二点回应中,我试图指出聚合只会处理源自自身的事件。这是因为事件是您的聚合的来源,因为事件构成了在该给定模型上发生的所有增量。WidgetAggregate 未存储在任何地方,而不是按原样存储。每次您从 axon 中检索您的聚合时Repository(这在 Axon 中为您自动完成),默认为EventSourcingRepository在 Axon 中,该给定聚合的所有事件都将从事件存储中检索。比,一个空聚合实例被创建,框架将重放它为该精确聚合实例找到的所有事件。因此,每次输入新命令时,您都可以有效地对聚合进行事件溯源。这听起来有点矫枉过正,因为给定聚合的事件数量可能会增长到相当大的集合。这可以通过做一些事情来解决,比如制作聚合的快照。ProjectedWidget)可以存储在您想要的任何格式和任何数据库/工具中,理想情况下没有任何业务逻辑。如果您发现自己在应用程序的查询端添加了业务逻辑,这可能建议您将此位升级为源自聚合的事件。我希望这能让您了解为什么要开始使用 Event Sourcing。这篇文章比我在这里做的更详细地描述了CQRS,还有这个关于事件溯源的链接;希望它们可以作为比我刚刚给你的更彻底的解释。