Spring @Autowired为什么不能与Java泛型一起使用


问题内容

受弹簧数据的启发,我想创建一个抽象的RESTController,可以将其扩展到很多控制器上。我创建了以下类:

@Controller
public abstract class RESTController<E, PK extends Serializable, R extends PagingAndSortingRepository<E, PK>>
{
    @Autowired
    private R repository;

    @RequestMapping(method=RequestMethod.GET, params={"id"})
    @ResponseBody 
    public E getEntity(@RequestParam PK id)
    {
        return repository.findOne(id);
    }

    ...
}

我希望泛型将允许我在存储库中使用@Autowired,但出现以下错误:

SEVERE: Allocate exception for servlet appServlet
org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.springframework.data.repository.PagingAndSortingRepository] is defined: expected single matching bean but found 3: [groupRepository, externalCourseRepository, managedCourseRepository]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:800)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:707)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:478)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:284)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:294)

我知道错误告诉我,@ Autowired有多个匹配项。我很困惑,因为我认为通过创建以下控制器它会起作用:

@Controller
@RequestMapping(value="/managedCourse")
public class ManagedCourseController extends RESTController<ManagedCourse, Long, ManagedCourseRepository>
{
    ...
}

通过在RESTController中使用如下方法可以轻松解决此问题:

protected abstract R getRepository();

然后在实现类中执行此操作:

@Autowired
private ManagedCourseRepository repository;

@Override
protected ManagedCourseRepository getRepository() 
{
    return repository;
}

我只是想知道是否有人对我如何使它起作用有任何想法。

我也发现了这个有趣的伯爵。


问题答案:

在这种情况下,我实际上建议在注释上进行基于XML的接线。在我看来,您正在尝试避免在控制器实例中进行很多不必要的重复。如果只有一个REST控制器类,则容器可以实例化所需的实例,将每个实例映射到不同的URI。

对于计划创建单个实例的情况,注释更多是一种简写形式。这恰好覆盖了约90%的基于表单的J2EE会话bean,但这不是万能的。