每个命令总是被发送到一个命令处理程序。 如果分派的命令没有可用的命令处理程序,则会引发 NoHandlerForCommandException 非常。
CommandBus 供应了两种方法将命令分派到它们各自的处理程序,分别是 dispatch(CommandMessage) 和 dispatch(CommandMessage, CommandCallback) 方法:
private CommandBus commandBus; // 1.public void dispatchCommands() { String cardId = UUID.randomUUID().toString(); // 2. // 3. & 4. commandBus.dispatch(GenericCommandMessage.asCommandMessage(new IssueCardCommand(cardId, 100, "shopId"))); // 5. & 6. commandBus.dispatch( GenericCommandMessage.asCommandMessage(new IssueCardCommand(cardId, 100, "shopId")), (CommandCallback<IssueCardCommand, String>) (cmdMsg, cmdResultMsg) -> { // 7. if (cmdResultMsg.isExceptional()) { Throwable throwable = cmdResultMsg.exceptionResult(); } else { String commandResult = cmdResultMsg.getPayload(); } } );}// omitted class, constructor and result usage
上面描述的 CommandDispatcher 举例解释了调度命令的几个主要方面和功能:

命令回调把稳事变
在利用 dispatch(CommandMessage, CommandCallback) 的情形下,调用组件可能不会假定回调是在分派命令的同一线程中调用的。 如果调用线程在连续之前依赖于结果,则可以利用 FutureCallback。 FutureCallback 是 Future(定义在 java.concurrent 包中)和 Axon 的 CommandCallback 的组合。 或者,考虑利用 CommandGateway。
命令网关'Command Gateway' 是一种用于调度命令的便捷方法。 它通过在 CommandBus 上调度命令时为您抽象某些方面来做到这一点。 它利用下面的 CommandBus 来实行的实际调度。虽然您不须要利用网关来分派命令,但它常日是最大略的选择。
CommandGateway 接口可以分为两组方法,即 send 和 sendAndWait:
private CommandGateway commandGateway; // 1.public void sendCommand() { String cardId = UUID.randomUUID().toString(); // 2. // 3. CompletableFuture<String> futureResult = commandGateway.send(new IssueCardCommand(cardId, 100, "shopId"));}// omitted class, constructor and result usage
如上所示的 send API 引入了几个观点,并标有编号的注释:
CommandGateway 接供词给发送命令的功能。它通过在内部利用 CommandBus 接口调度来实现。根据最佳实践,聚合标识符被初始化为随机唯一标识符的字符串。类型化的标识符工具也是可以的,只要该工具实现了一个合理的 toString() 函数。send(Object) 函数须要一个参数,即命令工具。这是一种调度命令的异步方法。因此 send 方法的相应是 CompletableFuture。这许可在返回命令结果后链接后续操作。利用 send(Object) 时的回调
CommandGateway#send(Object) 方法在后台利用 FutureCallback 来解除命令调度线程与命令处理线程的壅塞。
通过利用 sendAndWait 方法,也可以实现发送的同步方法:
private CommandGateway commandGateway;public void sendCommandAndWaitOnResult() { IssueCardCommand commandPayload = new IssueCardCommand(UUID.randomUUID().toString(), 100, "shopId"); // 1. String result = commandGateway.sendAndWait(commandPayload); // 2. result = commandGateway.sendAndWait(commandPayload, 1000, TimeUnit.MILLISECONDS);}// omitted class, constructor and result usage
CommandGateway#sendAndWait(Object) 函数接管一个参数,即您的命令工具。它将无限期地等待,直到命令调度和处理过程已经办理。该方法返回的结果可以是成功的,也可以是非常的,这里会阐明。如果不肯望无限期地等待,可以在命令工具阁下供应与 'time unit' 配对的 'timeout'。这样做将确保命令调度线程不会等待超过指定的韶光。如果在利用此方法时命令调度/处理被中断或超时,则命令结果将为 null。在所有其他情形下,结果遵照引用的方法。命令调度结果
一样平常来说,调度命令有两种可能的结果:
命令处理成功,并且命令处理非常结果在某种程度上取决于调度过程,但更多地取决于命令处理程序的实现。 因此,如果 @CommandHandler 表明的函数由于某些业务逻辑而引发非常,则该非常将成为调度命令的结果。
命令处理的成功办理故意不应供应任何返回工具。 因此,如果 CommandBus/CommandGateway 供应相应(直接或通过 CommandResultMessage),那么您该当假设命令处理成功的结果返回 null。
虽然可以从命令处理程序返回结果,但这该当很少利用。 命令的意图不应该是检索一个值,由于这表明该该当被设计为一个查询。 例外情形是聚合根的标识符,或聚合根已实例化的实体的标识符。 该框架在聚合的 @CommandHandler 表明布局函数中内置了一个这样的非常。 如果 “命令处理布局函数” 已成功实行,而不是聚合本身,将返回 @AggregateIdentifier 表明字段的值。