繁体   English   中英

使用泛型通过上下文获取 spring bean

[英]Get spring bean via context using generic

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

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

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

我找不到任何/有关此的文档。

你可以这样做:

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]);

如果你能确保对每一个具体子Node (说SomeNode ),该类型的每个对象SomeNode将是一个实际的SomeNode ,而不是一个子类,或者代理服务器,它会很容易。 只需使用存储库名称的约定(比如说SomeNodeRepository ),这将是微不足道的:

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

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

如果我理解得很好,你想获得具有Repository类和不同泛型类型的bean实例吗?

我是afraide你没有春天的动态方式,但我有一个解决方案:

  1. 您的泛型类型应该是类中的一个字段,您必须在Repository类中有一个构造函数来设置泛型类型,您的Repository类应该是这样的:

    public class Repository<T>{ Class<T> nodeClass; public Repository(Class<?> clazz){ this.nodeClass = clazz; } // your codes... }

  2. 为每个Node声明一个Repository bean,假设您有Repository和Repository,如果您使用的是xml配置,则需要添加:

    <bean id="someNodeRep" class="your.package.Repository"> <constructor-arg> <value>your.package.SomeNode</value> </constructor-arg> </bean> <bean id="otherNodeRep" class="your.package.Repository"> <constructor-arg> <value>your.package.OtherNode</value> </constructor-arg> </bean>

  3. 以这种方式“自动装配”您的存储库:

    @Autowired @Qualifier("someNodeRep") Repository<SomeNode> someNodeRepository;

    @Autowired @Qualifier("otherNodeRep") Repository<OtherNode> otherNodeRepository;

从 Spring 5.1 开始,您可以像这样获得Repository<T>类型的 bean:

public static <T> Repository<T> getRepositoryFor(Class<T> clazz)
{
    ResolvableType type = ResolvableType.forClassWithGenerics(Repository.class, clazz);
    return (Repository<T>) context.getBeanProvider(type).getObject();
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM