[英]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你没有春天的动态方式,但我有一个解决方案:
您的泛型类型应该是类中的一个字段,您必须在Repository类中有一个构造函数来设置泛型类型,您的Repository类应该是这样的:
public class Repository<T>{ Class<T> nodeClass; public Repository(Class<?> clazz){ this.nodeClass = clazz; } // your codes... }
为每个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>
以这种方式“自动装配”您的存储库:
@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.