获取所有在Spring中实现通用接口的bean [英] Get all beans implementing a generic interface in Spring

查看:1039
本文介绍了获取所有在Spring中实现通用接口的bean的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在Spring中获得实现特定通用接口(例如Filter < TestEvent >)的所有bean的引用?

How do I get a reference of all beans implementing a specific generic interface (e.g. Filter<TestEvent>) in Spring?

这是我想用最少的行数来实现的:

This is what I want to achieve with a minimum number of lines:

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在调用之前是否接受了该事件。
例如。

My current implementation uses reflection to determine if filter.approve does accept the event before calling it. 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
                }
            }
        }

其中,didFilterAcceptEventAsArgument完成了我想要摆脱的所有丑陋工作。有什么建议?

Where the doesFilterAcceptEventAsArgument does all the ugly work that I would like would like to get away from. Any suggestions?

推荐答案

如果你的问题是Spring有没有更好的方法来做到这一点,那么答案就是不。因此,您的方法看起来像无处不在的方法来实现这一点(获取原始类的所有bean,然后使用反射来查找泛型边界并将其与目标的类进行比较)。

If your question is "does Spring have a nicer way to do this", then the answer is "no". Hence, your method looks like the ubiquitous way to achieve this (get all beans of the raw class, then use reflection to look up the generic bound and compare it with the target's class).

通常,如果可能的话,在运行时使用通用信息很棘手。在这种情况下,您可以获得通用边界,但除了将其用作手动检查的注释形式之外,您实际上并没有从通用定义本身获得太多好处。

In general, using generic information at runtime is tricky if possible at all. In this case you can get the generic bounds, but you're not really getting much benefit from the generic definition itself, other than using it as a form of annotation to check manually.

在任何情况下,您都必须对返回的对象执行某种类型的检查,因此您的原始代码块无法正常工作;唯一的变化是在 doesFilterAcceptEventAsArgument 的实现中。经典的OO方式是使用以下两种方法添加一个抽象超类(并将后者添加到Filter接口):

In any case, you will have to perform some kind of check on the returned object, so your original code block isn't going to work; the only variation is in the implementation of doesFilterAcceptEventAsArgument. The classic OO way, would be to add an abstract superclass with two methods as follows (and add the latter to the Filter interface):

protected abstract Class<E> getEventClass();

public boolean acceptsEvent(Object event) // or an appropriate class for event
{
    return getEventClass().isAssignableFrom(event.getClass());
}

这是一种痛苦,因为你必须实现这个琐碎的 getEventClass()每个实现中的方法都返回相应的类文字,但这是泛型的已知限制。在语言的范围内,这可能是最干净的方法。

This is kind of a pain because you'll have to implement the trivial getEventClass() methods in every implementation to return the appropriate class literal, but it's a known limitation of generics. Within the bounds of the language, this is likely the cleanest approach.

但你的价值不错。

这篇关于获取所有在Spring中实现通用接口的bean的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆