春季:如何从实现通用接口的应用程序上下文中获取bean? [英] Spring: how to get bean from application context which implements generic interface?

查看:187
本文介绍了春季:如何从实现通用接口的应用程序上下文中获取bean?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有界面:

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

有些命令实现了 Command 标记界面

There are commands which implement Command marker interface

public class CreateCategoryCommand implements Command {
}

public class CreateCategoryCommand implements Command {
}

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

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

    }
}

问题: 我有命令总线

@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?

How to get bean from application context which implements generic interface with particular type?

推荐答案

我解决的方式:

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


}

这篇关于春季:如何从实现通用接口的应用程序上下文中获取bean?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆