【发布时间】:2021-11-27 16:41:00
【问题描述】:
我正在研究 ES 和 CQRS 系统的 PoC。
我定义了以下类来表示命令和事件,这些命令和事件代表正在处理的命令的输出
public class CreateEstateCommand extends Command {}
public class ChangeEstateOwnerCommand extends Command {}
public class EstateCreatedEvent extends DomainEvent {}
public class EstateOwnerChangedEvent extends DomainEvent {}
在实现以下接口的类中处理命令
/**
* Specific command handlers define what logic should be carried out during handling a command of type C.
* Single command execution results in an outcome of domain event of type E
*/
public interface CommandHandler<C extends Command, E extends DomainEvent> {
E handleCommand(C command);
}
public class EstateCreatedCommandHandler implements CommandHandler<CreateEstateCommand, EstateCreatedEvent> {
@Override
public EstateCreatedEvent handleCommand(CreateEstateCommand command) { /***/ }
}
public class ChangeEstateOwnerCommandHandler implements CommandHandler<ChangeEstateOwnerCommand, EstateOwnerChangedEvent> {
@Override
public EstateOwnerChangedEvent handleCommand(ChangeEstateOwnerCommand command) { /***/ }
}
现在是我想使用这些特定处理程序的部分。命令处理的流程可以表示如下:
命令通过API进入系统,转发给CommandServce类处理
public class CommandService {
private final EventService eventService;
private final CommandGateway commandGateway;
public void handleCommand(CreateEstateCommand command) {
EstateCreatedEvent event = commandGateway.handleCommand(command);
eventService.handleEvent(event);
}
public void handleCommand(ChangeEstateOwnerCommand command) {
EstateOwnerChangedEvent event = commandGateway.handleCommand(command);
eventService.handleEvent(event);
}
}
如您所见,handleCommand() 方法对于每个提交的命令都是重复的。这背后的原因是我在运行时选择适当的处理程序实现时遇到的问题,具体取决于Command.commandType:
@Service
public class CommandGateway {
private final Map<String, CommandHandler<?, ?>> commandHandlers;
@Autowired
public CommandGateway(Map<String, CommandHandler<?, ?>> commandHandlers) {
this.commandHandlers = commandHandlers;
}
public EstateCreatedEvent handleCommand(CreateEstateCommand command) {
EstateCreatedCommandHandler handler = (EstateCreatedCommandHandler) commandHandlers.get(command.getCommandType());
return handler.handleCommand(command);
}
public EstateOwnerChangedEvent handleCommand(ChangeEstateOwnerCommand command) {
ChangeEstateOwnerCommandHandler handler = (ChangeEstateOwnerCommandHandler) commandHandlers.get(command.getCommandType());
return handler.handleCommand(command);
}
}
上面的sn-p是我无法概括的部分。是否有可能,实现CommandGateway 类,所以CommandService 可以如下所示:
public class CommandService {
public <C extends Command, E extends DomainEvent> void handleCommand(C command) {
E event = commandGateway.handleCommand(command);
}
}
并提供类型安全的对象?
【问题讨论】:
-
我很确定“提供类型安全的对象”部分不是。泛型是仅编译时的构造,它们在运行时消失。而且由于您的查找是在运行时进行的,因此无法涉及泛型。为此,您将需要一些运行时信息。寻找 Joshua Block 的“类型安全异构容器”模式的想法。