Spring:如何从实现通用接口的应用程序上下文中获取bean?

时间:2016-10-05 18:25:36

标签: java spring generics dependency-injection

我有界面:

public interface CommandHandler<T extends Command> {
    void handle(T command);
}

有一些命令可以实现命令标记接口

public class CreateCategoryCommand implements Command {
}

public class CreateCategoryCommand implements Command {
}

对于每个命令,我都有适当的 CommandHandler 实现:

@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) {

    }
}

问题: 我有命令总线

@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()>)
    }
}

如何从实现具有特定类型的通用接口的应用程序上下文中获取bean?

1 个答案:

答案 0 :(得分:0)

我解决了它的方式:

@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;
    }


}