使用通用工具通过上下文获取春豆

2022-09-02 20:40:32

我有一堆实现类型的存储库bean。现在,我可以从用户那里获得随机节点的列表,并且我想为每个节点获取适当的存储库。从Spring 4.0RC1开始,我们可以像这样自动连接存储库:Repository<T ? extends Node>

@Autowired Repository<SomeNode> someNodeRepository;

如此所述。

这工作正常,但我的问题是我如何根据泛型类型动态执行此操作。

我想做的是这样的:

public <T extends Node> T saveNode(T node) {
    Repository<T> repository = ctx.getBean(Repository.class, node.getClass());
    return repository.save(node);
}

其中第二个参数是泛型类型。这当然不起作用,尽管它可以编译。

我找不到任何/这方面的文档。


答案 1

你可以做这样的事情:

String[] beanNamesForType = ctx.getBeanNamesForType(ResolvableType.forClassWithGenerics(Repository.class, node.getClass()));

// If you expect several beans of the same generic type then extract them as you wish. Otherwise, just take the first
Repository<T> repository = (Repository<T>) ctx.getBean(beanNamesForType[0]);

答案 2

如果你能确定对于(比如说)的每个具体子类,每个类型的对象都是实际的,而不是子类或代理,那就很容易了。只需使用存储库名称的约定(例如),这将是微不足道的:NodeSomeNodeSomeNodeSomeNodeSomeNodeRepository

Repository<T> repository = ctx.getBean(node.getClass().getSimpleName()
        + "Repository", Repository.class);

但是您知道,获得子类或代理的风险很高...

因此,您可以尝试让每个 Node 子类实现一个方法:nameForRepo

class Node {
    ...
    abstract String getNameForRepo();
}

然后在子类中

class SomeNode {
    static private final nameForRepo = "SomeNode";
    ...
    String getNameForRepo() {
        return nameForRepo;
    }
}

这样,即使您获得代理或子类,您也可以执行以下操作:

public <T extends Node> T saveNode(T node) {
    Repository<T> repository = ctx.getBean(node.getNameForRepository()
            + "Repository", Repository.class);
    return repository.save(node);
}

或者,该方法可以直接返回存储库名称。


推荐