我有一堆实现类型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);
}
其中第二个参数是泛型类型。 这当然不起作用,虽然它可以编译。
我无法找到关于此的任何/文档。
答案 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实例吗?
我是不是你没有春天的动态方式,但我有一个解决方案:
你的泛型类型应该是你的类中的一个字段,你的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
为每个Node声明一个Repository bean,假设您有Repository and Repository,如果您使用的是xml配置,则需要添加:
public class Repository<T>{
Class<T> nodeClass;
public Repository(Class<?> clazz){
this.nodeClass = clazz;
}
// your codes...
}
&#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;