理解@AggregateIdentifier & @TargetAggregateIdentifier

ama*_*ROT 1 cqrs event-sourcing axon axon-framework

所以我正在学习轴突框架,只是想巩固我对@TargetAggregateIdentifier注释的理解。

我的命令:

public class IssueCardCommand {

private String cardId;
private String versionNumber;
private Integer amount;

@TargetAggregateIdentifier
private String getAggregateIdentifier() {
    return (null != versionNumber) ? cardId + "V" + versionNumber : cardId;
    }
}
Run Code Online (Sandbox Code Playgroud)

我的聚合:

@Aggregate
@Slf4j
public class GiftCard {

private String giftCardId;
private String versionNumber;
private Integer amount;

@AggregateIdentifier
private String getAggregateIdentifier() {
    return (null != versionNumber) ? giftCardId + "V" + versionNumber : giftCardId;
}

public GiftCard() {
    log.info("empty noargs constructor");
}

@CommandHandler
public GiftCard(IssueCardCommand cmd) {
    log.info("handling {}",cmd);
    //this.giftCardId = cmd.getCardId();
    //this.versionNumber = cmd.getVersionNumber();
    apply(new CardIssuedEvent(cmd.getCardId(),cmd.getVersionNumber(),cmd.getAmount()));
}

@EventSourcingHandler
public void onCardIssuedEvent(CardIssuedEvent evt) {
    log.info("applying {}",evt);
    this.giftCardId = evt.getCardId();
    this.versionNumber = evt.getVersionNumber();
    this.amount = evt.getAmount();
    }
}
Run Code Online (Sandbox Code Playgroud)

所以这一切都按预期工作,并且事件被正确存储。但是,我只想确保我正确理解 @TargetAggregateIdentifier 和 @AggregateIdentifier 注释。

所以

@TargetAggregateIdentifier - 命令转到聚合的特定实例,因此需要告诉框架它是哪个实例,因此字段/方法上的此注释用于加载该特定聚合的事件?

我注意到当我在构造函数的命令中没有 @TargetAggregateIdentifier 时,代码仍然有效。但是如果它在任何后续命令中丢失,它会给出错误“无效命令,它无法识别目标聚合”,我觉得这证实了我上面的理解?

@AggregateIdentifier - 这告诉轴突框架这是标识符,因此当引入更多命令时,它需要存储该特定聚合的事件?

如果有人能指出我的理解是否正确并在不正确的地方发表评论,我将不胜感激,以便我可以以正确的方式使用该框架。

谢谢。

Mil*_*kov 5

我已经在最初发布问题的 AxonIQ 讨论平台上提供了答案

由于使用链接回答只会违反 SO 的礼仪,因此我也在这里回答我的回答:

我猜你的理解是正确的。但是让我给你一个简化的过程解释,这样你就可以将它与你目前的理解进行比较。

当您发出创建新聚合(由聚合的构造函数处理的聚合)的命令时,不需要标识符。原因是您正在创建一个新实例,而不是加载现有实例。在这种情况下,框架只需要聚合的 FQCN 即可创建它的实例。它可以轻松找到 FQCN,因为它知道(通过聚合注册期间的检查)哪个聚合可以处理此类创建命令。这就是为什么在没有@TargetAggregateIdentifier工作的情况下创建命令就好了。

一旦创建命令被处理,聚合的状态需要存储在某处。

  • 对于事件源聚合,所有状态更改事件都存储在事件存储中
  • 对于状态存储聚合,整个状态存储在存储库中

在这两种情况下,框架都需要知道如何识别这些数据。这@AggregateIdentifier就是为了。它告诉框架以可通过特定标识符识别的方式存储数据。您可以将其视为 DB 术语中的主键。

当您向聚合的现有实例发送命令时,您需要告诉它是哪个实例。您可以通过提供一个 @TargetAggregateIdentifier . 然后框架将创建相应聚合的新空实例,然后尝试将数据加载到其中

  • 通过读取与该实例相关的所有过去事件来获取事件源聚合
  • 通过从存储库读取当前状态来获取状态存储的聚合

在这两种情况下,框架都将搜索可通过 的值识别的数据@TargetAggregateIdentifier。加载聚合数据后,它将继续处理命令。