Axon 使用无参数构造函数隐式实例化另一个聚合

Axon implicitly instantiate another aggregate using paramless constructor

我只是想知道为什么 Axon 隐式实例化另一个聚合。此行为会导致多个事件处理,我认为这种开销不是预期的。 具有此端点:

@PostMapping("ship")
public void shipOrder(@RequestBody Product product) {
        String orderId = UUID.randomUUID().toString();
        commandGateway.sendAndWait(new PlaceOrderCommand(orderId, product.getName()));
        commandGateway.sendAndWait(new ConfirmOrderCommand(orderId));
}

和以下合计:

@Aggregate
public class Order {

    @AggregateIdentifier
    private String orderId;
    private boolean orderConfirmed;

    @CommandHandler
    public Order(PlaceOrderCommand command) {
        System.out.println("Calling COMMAND constructor");
        apply(new OrderPlacedEvent(command.getOrderId(), command.getProduct()));
    }

    protected Order() {
        System.out.println("Calling PARAMLESS constructor");
    }

    @CommandHandler
    public void handle(ConfirmOrderCommand command) {
        apply(new OrderConfirmedEvent(command.getOrderId()));
    }

    @EventSourcingHandler
    public void on(OrderPlacedEvent event) {
        System.out.println(">>>>>> Handling OrderPlacedEvent: " + this);
        this.orderId = event.getOrderId();
        orderConfirmed = false;
    }

    @EventSourcingHandler
    public void on(OrderConfirmedEvent event) {
        System.out.println(">>>>>> Handling OrderConfirmedEvent: " + this);
        orderConfirmed = true;
    }
}

在我收到此日志后调用端点后:

Calling COMMAND constructor
>>>>>> Handling OrderPlacedEvent: Order@3eecb9e2
Calling PARAMLESS constructor
>>>>>> Handling OrderPlacedEvent: Order@cd10277
>>>>>> Handling OrderConfirmedEvent: Order@cd10277

如您所见,OrderPlacedEvent 被调用了两次,连同不带参数的构造函数。有人知道我为什么会出现以下行为吗?

当您使用事件溯源时,这种行为是正确的并且是预期的。在事件溯源中,每当您向聚合发送命令时,它都会首先加载所有先前的事件以补充聚合并确定其当前状态。这些事件是您的真实来源。除了一些例外,聚合的当前状态未被存储。

因此,一般来说,您应该确保只在聚合中使用 EventSourcingHandler 来填充其状态。

请注意,一旦系统增长很多,聚合可能会包含大量需要读取的事件。如果发生这种情况,您可以通过在每个 n 事件后存储聚合快照(当前状态)来进行一些优化。这样您就不必加载超过 n 个事件。