[英]Get all beans implementing a generic interface in Spring
如何在Spring中获得实现特定通用接口(例如Filter <TestEvent
>)的所有bean的引用?
这是我想用最少的行数实现的:
public interface Filter<T extends Event> {
boolean approve(T event);
}
public class TestEventFilter implements Filter<TestEvent> {
public boolean approve(TestEvent event){
return false;
}
}
public class EventHandler{
private ApplicationContext context;
public void Eventhandler(DomainEvent event) {
// I want to do something like following, but this is not valid code
Map<String, Filter> filters = context.getBeansOfType(Filter<event.getClass()>.class);
for(Filter filter: filters.values()){
if (!filter.approve(event)) {
return; // abort if a filter does not approve the event
}
}
//...
}
}
我当前的实现使用反射来确定filter.approve在调用之前是否接受了该事件。 例如
Map<String, Filter> filters = context.getBeansOfType(Filter.class);
for(Filter filter: filters.values()){
if (doesFilterAcceptEventAsArgument(filter, event)) {
if (!filter.approve(event)) {
return; // abort if a filter does not approve the event
}
}
}
在什么地方,doFilterAcceptEventAsArgument完成了我想要摆脱的所有丑陋的工作。 有什么建议?
仅供参考,我可以构建的最简单的解决方案是:
Map<String, Filter> filters = context.getBeansOfType(Filter.class);
for(Filter filter: filters.values()){
try {
if (!filter.approve(event)) {
return; // abort if a filter does not approve the event.
}
} catch (ClassCastException ignored){ }
}
它在原型设计方面表现得非常好。
如果你的问题是“Spring是否有更好的方法来做到这一点”,那么答案就是“不”。 因此,您的方法看起来像无处不在的方法来实现这一点(获取原始类的所有bean,然后使用反射来查找泛型边界并将其与目标的类进行比较)。
通常,如果可能的话,在运行时使用通用信息很棘手。 在这种情况下,您可以获得通用边界,但除了将其用作手动检查的注释形式之外,您并没有从通用定义本身获得太多好处。
在任何情况下,您都必须对返回的对象执行某种检查,因此您的原始代码块无法正常工作; 唯一的变化是在doesFilterAcceptEventAsArgument
的实现中。 经典的OO方式是使用以下两种方法添加一个抽象超类(并将后者添加到Filter接口):
protected abstract Class<E> getEventClass();
public boolean acceptsEvent(Object event) // or an appropriate class for event
{
return getEventClass().isAssignableFrom(event.getClass());
}
这是一种痛苦,因为你必须在每个实现中实现简单的getEventClass()
方法来返回相应的类文字,但这是已知的泛型限制。 在语言的范围内,这可能是最干净的方法。
但你的价值不错。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.