简体   繁体   English

为什么spring @Autowired不能使用java泛型

[英]Why doesn't the spring @Autowired work with java generics

Inspired by spring data awesomeness I wanted to create a abstract RESTController that I could extend for a lot of my controllers. 受到spring数据的启发,我想创建一个抽象的RESTController,我可以为很多控制器进行扩展。 I created the following class: 我创建了以下类:

@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);
    }

    ...
}

I was hoping that the generics would allow me to @Autowired in the repository but I get the following error: 我希望generics允许我在存储库中@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)

I understand what the error is telling me, there is more than one match for the @Autowired. 我理解错误告诉我的是,@ Aututired有多个匹配。 I am confused because I thought by creating the following controller it would work: 我很困惑,因为我想通过创建以下控制器它会工作:

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

This is easy enough to work around by doing having a method like this in the RESTController: 这很容易通过在RESTController中使用这样的方法来解决:

protected abstract R getRepository();

and then doing this in your implementing class: 然后在您的实现类中执行此操作:

@Autowired
private ManagedCourseRepository repository;

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

I was just wondering if someone had any thoughts of how I could get this to work. 我只是想知道是否有人想到如何让这个工作。

Also I found this interesting aritcle. 我也发现了这个有趣的aritcle。

I don't think there is any way to get this work with Spring. 我认为没有办法让Spring使用它。 I have read the source code of Spring Ioc before, and find that it doesn't care the Generic Declaration on Class Level, but just Field or Method Parameter. 我之前已经阅读过Spring Ioc的源代码,并发现它并不关心类级别的通用声明,而只关注字段或方法参数。 Look in to class org.springframework.beans.factory.config.DependencyDescriptor if you are interested, and you'll find what I said. 如果你有兴趣,请查看org.springframework.beans.factory.config.DependencyDescriptor类,你会发现我说的话。

I would actually recommend XML-based wiring over annotations in this case. 在这种情况下,我实际上会建议基于XML的注释。 It seems to me you're trying to avoid a lot of needless duplication in your controller instances. 在我看来,你试图避免在你的控制器实例中进行大量不必要的重复。 If you had a single REST controller class, the container can then instantiate as many instances as you need, mapping each to a different URI. 如果您有一个REST控制器类,则容器可以根据需要实例化任意数量的实例,并将每个实例映射到不同的URI。

Annotations are more of a shorthand for cases where you plan to create a single instance. 对于计划创建单个实例的情况,注释更多是一种简写。 This happens to cover about 90% of form-based J2EE session beans, but it's not a panacea. 这恰好涵盖了大约90%的基于表单的J2EE会话bean,但它并不是灵丹妙药。

Spring使用成员的类型来“自动连接”它,因此使用泛型只提供通用类型信息,而不是您希望spring为您注入的特定类型。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM