Java 处理Axon中的非平凡命令和事件有效负载

Java 处理Axon中的非平凡命令和事件有效负载,java,spring,axon,Java,Spring,Axon,每当我看一眼,我就会开始思考是否应该遵循一组事件和命令的设计规则 在Axon Bank中,事件和命令完全由原语组成。在我的应用程序中,我倾向于尽可能避免原始用法,主要是为了构建一个表达域,并在任何我能得到的地方都具有类型安全性 Axon本身附带了一些DDD引用,但无论我浏览哪个文档,都没有一个示例将复合对象用作事件/命令有效负载的一部分 这让我很困惑。它内置了对全面的xml和json序列化的支持,不仅能够拥有一些键值对 我理解,尤其是事件往往是小而简单的结构,因为它们只反映增量状态更改,但在复杂

每当我看一眼,我就会开始思考是否应该遵循一组事件和命令的设计规则

在Axon Bank中,事件和命令完全由原语组成。在我的应用程序中,我倾向于尽可能避免原始用法,主要是为了构建一个表达域,并在任何我能得到的地方都具有类型安全性

Axon本身附带了一些DDD引用,但无论我浏览哪个文档,都没有一个示例将复合对象用作事件/命令有效负载的一部分

这让我很困惑。它内置了对全面的xml和json序列化的支持,不仅能够拥有一些键值对

我理解,尤其是事件往往是小而简单的结构,因为它们只反映增量状态更改,但在复杂域模型和事件(条目)之间总会有某种差距


在我的领域中,我可以有很多类,比如
透支限额
当前余额
存款
账户标识符

现在有两种可能的方法来设计事件和命令:

1.基元与广义转换
  • 将事件视为原始数据,并在其上添加一个漂亮的标签
  • 一旦原始数据“进入”应用程序,就将其转换为功能强大的对象
  • 创建事件时,只需再次将其剥离

    public class BankAccountcreatedEvent {
        private final String accountIdentifier;
        private final int overdraftLimt;
    
        // ...
    }
    
    在其他地方:

    public void on (BankAccountCreatedEvent event) {
        this.accountIdentifier = AccountIentifier.fromString(event.getAccountIdentifier());
        this.overdraftLimit = new OverdraftLimit(event.getOverdraftLimit());
    }
    
优点:

  • 没有任何奇怪依赖项的简单命令/事件API
  • 使分发更容易
  • 只有当实际事件结构发生变化,因此可以很容易地预测时,才需要向上广播
缺点:

  • 需要编写和维护一个巨大的转换层
  • 由于主要技术原因,将事件/命令与域模型的其余部分分离会引入一个新的、人为的上下文间隙
2.表达有效载荷
  • 直接使用复杂类型作为属性

    public class BankAccountCreatedEvent {
        private final BankAccountIdentifier bankAccountIdentifier;
        private final OverdraftLimit overdraftLimit;
    
        //..
    }
    
优点:

  • 写得少,读起来容易
  • 把本来应该在一起的东西放在一起
缺点:

  • 域逻辑间接地影响事件结构,需要更频繁地进行向上转换,并且不太可预测

我需要第二个意见。有推荐的方式吗?

首先要记住的是,活动的序列化形式是您的正式合同。在Java类中如何表示这一点最终取决于每个应用程序。例如,如果将序列化程序配置为忽略未知字段,则可以将不关心的字段保留在外

public class BankAccountCreatedEvent {
    private final BankAccountIdentifier bankAccountIdentifier;
    private final OverdraftLimit overdraftLimit;

    //..
}
就我个人而言,我不介意事件中的原语。但是,我确实理解在某些字段中使用显式值对象的价值,因为它们允许您表达每个字段所涉及的“数学”。在标识符的情况下,它们可以防止“混淆”,即标识符被用于意外地尝试标识另一种类型的对象

最后,这没什么大不了的。通过一些简单的Jackson注释,您可以将这些值对象转换为JSON中的简单值。例如,退房

public class BankAccountCreatedEvent {
    private final BankAccountIdentifier bankAccountIdentifier;
    private final OverdraftLimit overdraftLimit;

    //..
}
将映射到:

{
    "bankAccountIdentifier": "abcdef1234",
    "overdraftLimit" : 1000
}
如果BankAccountIdentifier和OverdraftLimit类都有@JsonValue注释方法,该方法将返回它们的“简单”值