如何在Spring中获得实现特定通用接口(例如Filter <TestEvent
&gt;)的所有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在调用之前是否接受了该事件。 E.g。
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完成了我想要摆脱的所有丑陋工作。有什么建议?
答案 0 :(得分:5)
仅供参考,我可以构建的最简单的解决方案是:
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){ }
}
它适用于原型制作。
答案 1 :(得分:2)
如果您的问题是“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()
方法来返回相应的类文字,但这是已知的泛型限制。在语言的范围内,这可能是最干净的方法。
但你的价值不错。