java - 在调用 EventSourcingHandlers 之间如何保留实体的状态?

标签 java kotlin persistence axon

Axon Giftcard demo ,有一个 GiftCard 类,注释为@Aggregate:

@Aggregate
@Profile("command")
public class GiftCard {

    private final static Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

    @AggregateIdentifier
    private String id;
    private int remainingValue;

    @CommandHandler
    public GiftCard(IssueCmd cmd) {
        log.debug("handling {}", cmd);
        if(cmd.getAmount() <= 0) throw new IllegalArgumentException("amount <= 0");
        apply(new IssuedEvt(cmd.getId(), cmd.getAmount(), cmd.getCurrency()));
    }

    @CommandHandler
    public void handle(RedeemCmd cmd) {
        log.debug("handling {}", cmd);
        if(cmd.getAmount() <= 0) throw new IllegalArgumentException("amount <= 0");
        if(cmd.getAmount() > remainingValue) throw new IllegalStateException("amount > remaining value");
        apply(new RedeemedEvt(id, cmd.getAmount()));
    }

...
    @EventSourcingHandler
    public void on(IssuedEvt evt) {
        log.debug("applying {}", evt);
        id = evt.getId();
        remainingValue = evt.getAmount();
        currency = evt.getCurrency();
        log.debug("new remaining value: {}", remainingValue);
        log.debug("new currency: {}", currency);
    }

   @EventSourcingHandler
    public void on(RedeemedEvt evt) {
        log.debug("applying {}", evt);
        remainingValue -= evt.getAmount();
        log.debug("new remaining value: {}", remainingValue);
    }
...

命令和事件类在 Kotlin 代码中定义:

data class IssueCmd(@TargetAggregateIdentifier val id: String, val amount: Int)
data class IssuedEvt(val id: String, val amount: Int)
data class RedeemCmd(@TargetAggregateIdentifier val id: String, val amount: Int)
data class RedeemedEvt(val id: String, val amount: Int)

假设以下两个命令被放置在命令总线上:

Command #     Command Class   id          amount
---------     -------------   -------     -------------
1             IssueCmd        QP34        123.45
2             RedeemCmd       QP34        38.10

处理第一个命令时,IssueCmd 的 CommandHandler (CH) 将在事件总线上放置一个 IssuedEvt 对象。该事件将由 IssuedEvt 的 EventSourcingHandler (ESH) 进行处理。然后,我们将拥有一个 GiftCard 实例,其 id 设置为“QP34”,remainingValue 设置为 >123.45

处理第二个命令时,RedeemCmd 的 CH 会将一个 RedeemedEvt 对象放在事件总线上。该事件将由 ESH 处理 RedeeemedEvt。然后,我们将拥有一个 GiftCard 实例,其 id 设置为“QP34”,remainingValue 设置为 >85.35

问题:每个事件由其指定的 ESH 处理后,生成的对象实例如何以及在何处持续存在?

之前,我听到的答案是:确实没有。所有持续存在的都是事件对象,它们保存在 Axon 的事件存储中。当需要对象的当前状态时,Axon 告诉命令模型启动 GiftCard 类的实例,并从最早到最晚的时间对其应用事件。这就是事件溯源的定义。

但是,在事件溯源时,处理 IssuedEvt 后,remainingValue 中的 123.45 必须保留在某处,以便 ESH使 RedeemedEvt 的减法运算具有正确的值。

在调用 ESH 之间如何以及在何处保留对象状态?

最佳答案

框架在内部实例化 AnnotatedAggregate当您检索Aggregate时来自 Repository 的实例.

AnnotatedAggregate类实现 Aggregate ,其中Repository接口(interface)强制为 load(String) 上的返回类型操作。

当您谈论事件溯源时,Repository正在使用的实现是 EventSourcingRepository ,在load(String)上返回 EventSourcedAggregate实例(这是 AnnotatedAggregate 的实现。

Aggregate接口(interface),AnnotatedAggregate该接口(interface)和 EventSourcedAggregate 的实现再次实现它,定义一个泛型。

此泛型是的聚合实现。

当您通过EventSourcingRepository对聚合进行事件溯源时,您的聚合实例保存在 AnnotatedAggregate内存中下private T aggregateRoot全局领域。

这个aggregateRootEventSourcingRepository 更新,它初始化 EventSourcedAggregate 的状态通过给它一个 EventMessages 的流.

顺便问一下,@JonathanM,你为什么对这一点感兴趣?

以下是这些类的 GitHub 链接,供引用:

  1. Aggregate
  2. AnnotatedAggregate
  3. EventSourcedAggregate
  4. Repository
  5. EventSourcingRepository

关于java - 在调用 EventSourcingHandlers 之间如何保留实体的状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54988020/

相关文章:

java - 动态改变Jtree中一个或多个节点的颜色

java - Solr 空间距离错误

java - 从后台线程调用主线程上的函数

java - 将java对象转换为相应类型的xml

sql-server - 旧数据存储在数据库文件中

java - 将 MySQL 几何图形映射到 EJB 实体时出错

c++ - 如何使用数据访问对象进行序列化和关系数据库数据访问

java - 如何在不抬起手指的情况下更改我按下的按钮? (在 LibGDX 中)

android - Kotest(以前的 KotlinTest)在 Android Studio 中还能用吗?

java - 如何使用可分页参数定义请求方向?