I have interface:
public interface CommandHandler<T extends Command> {
void handle(T command);
}
There are commands which implement Command marker interface
public class CreateCategoryCommand implements Command {
}
public class CreateCategoryCommand implements Command {
}
For each command I have apropriate CommandHandler implementations:
@Component
public class CreateProductCommandHandler implements CommandHandler<CreateProductCommand> {
@Override
public void handle(CreateProductCommand command) {
System.out.println("Command handled");
}
}
@Component
public class CreateCategoryCommandHandler implements CommandHandler<CreateCategoryCommand> {
@Override
public void handle(CreateCategoryCommand command) {
}
}
Question: I have command bus
@Component
public class SimpleCommandBus implements CommandBus {
@Autowired
private ApplicationContext context;
@Override
public void send(Command command) {
// OF COURSE, THIS NOT COMPILED, BUT I NEED SOMETHING LIKE THIS
CommandHandler commandHandler = context.getBean(CommandHandler<command.getClass()>)
}
}
How to get bean from application context which implements generic interface with particular type?
getBean() method. Simply put, as the name of the method also suggests, this is responsible for retrieving a bean instance from the Spring container.
The Spring container recognizes that LocalSessionFactoryBean implements the FactoryBean interface, and thus treats this bean specially: An instance of LocalSessionFactoryBean is instantiated, but instead of being directly returned, instead the getObject() method is invoked.
You can call applicationContext. getBeanDefinitionNames() method to list all beans loaded into ApplicationContext.
Way I solved it:
@Component
public class SimpleCommandBus {
private final Logger logger;
private final Set<CommandHandler<?>> handlers;
private final Map<Class<?>, CommandHandler<?>> commandHandlersCache = new WeakHashMap<>();
public SimpleCommandBus(Logger logger, Set<CommandHandler<?>> handlers) {
this.logger = logger;
this.handlers = handlers;
}
public void send(Command command) {
CommandHandler<Command> commandHandler = getCommandHandler(command);
if (commandHandler != null)
commandHandler.handle(command);
else
logger.error("Can't handle command " + command);
}
@SuppressWarnings("unchecked")
private <C extends Command> CommandHandler<C> getCommandHandler(C command) {
Class<?> commandType = command.getClass();
if (commandHandlersCache.containsKey(commandType))
return (CommandHandler<C>) commandHandlersCache.get(commandType);
for (CommandHandler<?> haandler : handlers) {
Class<?> supportedCommandType = resolveTypeArgument(haandler.getClass(), CommandHandler.class);
if (commandType.isAssignableFrom(supportedCommandType)) {
commandHandlersCache.put(commandType, haandler);
return (CommandHandler<C>) haandler;
}
}
commandHandlersCache.put(commandType, null);
return null;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With