使用泛型

时间:2015-05-21 12:49:18

标签: java spring generics

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

@Autowired Repository<SomeNode> someNodeRepository;

记录在案here

这很好用,但我的问题是我如何根据泛型类型动态地执行此操作。

我想做的是:

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

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

我无法找到关于此的任何/文档。

3 个答案:

答案 0 :(得分:15)

您可以这样做:

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

答案 1 :(得分: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);
}

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

答案 2 :(得分:0)

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

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

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

    .data .asciiz "c" .asciiz "hello world\n" .globl main .text main: lui $a0, 0x1002 # set $a0 to start of string addi $v0, $0, 4 # set command to print syscall

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

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

  3. &#39;自动装配&#39;以这种方式存储您的存储库:

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

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