为什么需要 EventSourcingHandler(在聚合对象中)?
Why is EventSourcingHandler (in aggregate object) needed?
公平警告:我不知道自己在做什么,所以即使问这个问题也可能出错。
我想更新一个简单对象(聚合)的状态,然后向 UI 提供已更改对象的投影。这是我的聚合对象(存在命令处理程序,但未在此处显示)。
@Aggregate
public class Widget {
@AggregateIdentifier
private String id;
private String color;
...
@EventSourcingHandler
public void on(ChangeColorEvt evt) {
color = evt.getColor();
}
...
}
...这是我的预测:
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);
}
...
}
QueryHandler 执行您期望的操作,找到实例并返回它。
所以这是我的问题:
- 为什么我需要聚合中的 EventSourcingHandler?这就对了
似乎可以工作,但结果不会存储或发送到任何地方。
- 所以,这成为我的下一个问题:执行 EventSourcing 之后
Handler,是 Widget 的结果实例(不是投影)
存储、查看或发送到任何地方?
- 如果确实需要EventSourcingHandler,有没有办法避免
有两个独立的业务逻辑副本(一个在
EventSourcingHandler 和一个 EventHandler)?我真的很讨厌这个主意
必须在两个地方更新相同的业务逻辑。
我感谢该小组提供的任何清晰信息。感谢您的帮助!
希望能帮到你解决这个问题!
简短的回答是:
使用 @EventSourcingHandler
的必要性实际上取决于您希望如何为应用程序建模。
现在,这并没有说明什么,所以让我详细说明一下我为什么要这么说。
在回答您的问题时,我假设您希望创建一个遵循 DDD、CQRS 和事件溯源思想的应用程序。因此,Axon 在构建您的应用程序时试图为您简化的概念。
让我从这里回顾一下你的编号问题:
- 您在聚合中需要
@EventSourcingHandler
注释函数的原因是 (1) 根据 它 具有的 (2) 个事件更新聚合状态出版。要转到第 1 点,为什么要更新聚合的状态?由于聚合是应用程序的命令模型,因此它的任务是根据收到的命令做出决策。为了能够做出决定,有时聚合需要状态,但有时不需要。因此,在您共享的 Widget
示例中,我假设 color
字段根本不用于稍后驱动业务逻辑,因此您可以完全从聚合中省略此状态,而无需任何问题。对于我回应的第二点,我试图指出聚合只会处理源自其自身的事件。这是因为事件是聚合的来源,因为事件构成了给定模型上发生的所有增量。
- 你的以下问题非常适合继续我在第 1 点开始的解释。答案很简单,你的
Widget
聚合没有存储在任何地方,而不是 原样。每次您从 Repository
检索聚合(这在 Axon 中自动为您完成),在 Axon 中默认为 EventSourcingRepository
,该给定聚合的所有事件都将从活动商店。然后,创建一个 empty 聚合实例,框架将重播它为该聚合实例找到的所有事件。因此,每次收到新命令时,您都在有效地对聚合进行事件溯源。这听起来有点矫枉过正,因为给定聚合的事件数量可能会增长到相当大的集合。这可以通过做聚合的 snapshots 之类的事情来解决。
- 如果这种形式将您的应用程序拆分为处理您的业务逻辑的专用部分、命令模型,以及仅 returns 作为答案的查询模型的部分,即查询模型,那么您可以决定要 State Stored Aggregate。所以请注意,在使用 Axon 时,您根本不需要进行事件溯源;这只是框架的默认操作方式。因此,我理解您的担忧,即您在重复您的逻辑。但是,您可以严格分离做出所有决定的部分,这些决定将保存在您的聚合中。
查询模型(在您的示例中为
ProjectedWidget
)可以以您想要的任何格式和 database/tool 存储,理想情况下没有任何业务逻辑。
如果您确实发现自己在应用程序的查询端添加业务逻辑,这可能建议您应该将此位升级为源自聚合的事件。
我希望这能让您深入了解为什么要开始使用事件溯源。本文介绍了 CQRS in a little more detail than I could do here, and this link 事件溯源;希望它们可以作为比我刚才给你的解释更彻底的解释。
公平警告:我不知道自己在做什么,所以即使问这个问题也可能出错。
我想更新一个简单对象(聚合)的状态,然后向 UI 提供已更改对象的投影。这是我的聚合对象(存在命令处理程序,但未在此处显示)。
@Aggregate
public class Widget {
@AggregateIdentifier
private String id;
private String color;
...
@EventSourcingHandler
public void on(ChangeColorEvt evt) {
color = evt.getColor();
}
...
}
...这是我的预测:
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);
}
...
}
QueryHandler 执行您期望的操作,找到实例并返回它。
所以这是我的问题:
- 为什么我需要聚合中的 EventSourcingHandler?这就对了 似乎可以工作,但结果不会存储或发送到任何地方。
- 所以,这成为我的下一个问题:执行 EventSourcing 之后 Handler,是 Widget 的结果实例(不是投影) 存储、查看或发送到任何地方?
- 如果确实需要EventSourcingHandler,有没有办法避免 有两个独立的业务逻辑副本(一个在 EventSourcingHandler 和一个 EventHandler)?我真的很讨厌这个主意 必须在两个地方更新相同的业务逻辑。
我感谢该小组提供的任何清晰信息。感谢您的帮助!
希望能帮到你解决这个问题!
简短的回答是:
使用 @EventSourcingHandler
的必要性实际上取决于您希望如何为应用程序建模。
现在,这并没有说明什么,所以让我详细说明一下我为什么要这么说。 在回答您的问题时,我假设您希望创建一个遵循 DDD、CQRS 和事件溯源思想的应用程序。因此,Axon 在构建您的应用程序时试图为您简化的概念。
让我从这里回顾一下你的编号问题:
- 您在聚合中需要
@EventSourcingHandler
注释函数的原因是 (1) 根据 它 具有的 (2) 个事件更新聚合状态出版。要转到第 1 点,为什么要更新聚合的状态?由于聚合是应用程序的命令模型,因此它的任务是根据收到的命令做出决策。为了能够做出决定,有时聚合需要状态,但有时不需要。因此,在您共享的Widget
示例中,我假设color
字段根本不用于稍后驱动业务逻辑,因此您可以完全从聚合中省略此状态,而无需任何问题。对于我回应的第二点,我试图指出聚合只会处理源自其自身的事件。这是因为事件是聚合的来源,因为事件构成了给定模型上发生的所有增量。 - 你的以下问题非常适合继续我在第 1 点开始的解释。答案很简单,你的
Widget
聚合没有存储在任何地方,而不是 原样。每次您从Repository
检索聚合(这在 Axon 中自动为您完成),在 Axon 中默认为EventSourcingRepository
,该给定聚合的所有事件都将从活动商店。然后,创建一个 empty 聚合实例,框架将重播它为该聚合实例找到的所有事件。因此,每次收到新命令时,您都在有效地对聚合进行事件溯源。这听起来有点矫枉过正,因为给定聚合的事件数量可能会增长到相当大的集合。这可以通过做聚合的 snapshots 之类的事情来解决。 - 如果这种形式将您的应用程序拆分为处理您的业务逻辑的专用部分、命令模型,以及仅 returns 作为答案的查询模型的部分,即查询模型,那么您可以决定要 State Stored Aggregate。所以请注意,在使用 Axon 时,您根本不需要进行事件溯源;这只是框架的默认操作方式。因此,我理解您的担忧,即您在重复您的逻辑。但是,您可以严格分离做出所有决定的部分,这些决定将保存在您的聚合中。
查询模型(在您的示例中为
ProjectedWidget
)可以以您想要的任何格式和 database/tool 存储,理想情况下没有任何业务逻辑。 如果您确实发现自己在应用程序的查询端添加业务逻辑,这可能建议您应该将此位升级为源自聚合的事件。
我希望这能让您深入了解为什么要开始使用事件溯源。本文介绍了 CQRS in a little more detail than I could do here, and this link 事件溯源;希望它们可以作为比我刚才给你的解释更彻底的解释。