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

别来无恙 提交于 2019-12-10 10:07:57

问题


Inspired by spring data awesomeness I wanted to create a abstract RESTController that I could extend for a lot of my controllers. 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:

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. 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:

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.


回答1:


I would actually recommend XML-based wiring over annotations in this case. 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.

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.




回答2:


I don't think there is any way to get this work with 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. Look in to class org.springframework.beans.factory.config.DependencyDescriptor if you are interested, and you'll find what I said.




回答3:


Spring uses the type of the member to "auto-wire" it, so using generics you only provide the generic type info not the specific type you want spring to inject for you.



来源:https://stackoverflow.com/questions/10844466/why-doesnt-the-spring-autowired-work-with-java-generics

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!