Java 泛型类型的Spring问题

Java 泛型类型的Spring问题,java,spring,generics,Java,Spring,Generics,我在使用泛型时遇到了Spring的问题。 以下代码很好地描述了该问题: public class TestInj<S> { S elem; public S getElem() { return elem; } public void setElem(S elem) { this.elem = elem; } } @Component public class First extends TestInj<

我在使用泛型时遇到了Spring的问题。 以下代码很好地描述了该问题:

public class TestInj<S> {
    S elem;
    public S getElem() {
        return elem;
    }
    public void setElem(S elem) {
        this.elem = elem;
    }
}

@Component
public class First extends TestInj<String> {
    public First() {
        setElem("abc");
    }
}

@Component
public class Second extends TestInj<Integer> {
    public Second() {
        setElem(2);
    }
}



public class BaseTest<T> {
    @Autowired
    protected TestInj<T> test;

}

@Named
public class Test extends BaseTest<String> {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("conf-spring.xml");
        context.refresh();
        Test test = (Test) context.getBean("test", Test.class);
        System.out.println(test.test.getElem());
    }
}
公共类测试j{
S元素;
公共服务{
返回元素;
}
公共无效集合元素(S元素){
this.elem=elem;
}
}
@组成部分
公共类优先扩展TestInj{
公共优先{
setElem(“abc”);
}
}
@组成部分
公共类二级扩展{
公共第二{
setElem(2);
}
}
公共类基类测试{
@自动连线
保护试验;
}
@命名
公共类测试扩展了BaseTest{
公共静态void main(字符串[]args){
ClassPathXmlApplicationContext上下文=新的ClassPathXmlApplicationContext(“conf spring.xml”);
context.refresh();
Test=(Test)context.getBean(“Test”,Test.class);
System.out.println(test.test.getElem());
}
}

问题是,在类BaseTest中,应该首先注入类,因为它具有泛型类型字符串。但是spring不明白这一点,他告诉我,自动布线有两种可能的选择。原因是spring忽略了泛型。是否有解决方案或解决方法?

这是由于类型擦除。见:

当一个泛型类型被实例化时,编译器通过一种称为类型擦除的技术来翻译这些类型——编译器在这个过程中删除与类或方法中的类型参数和类型参数相关的所有信息。类型擦除使使用泛型的Java应用程序能够与在泛型之前创建的Java库和应用程序保持二进制兼容性。


由于Spring DI容器在运行时工作,它无法区分这些类型。

Spring在泛型方面非常聪明,但您的要求太高了。Spring分析包含要注入的属性的类的泛型,即
BaseTest
。但是依赖项
test
的类型擦除是
TestInj
。只有子类
Test
提供了更多的通用信息,这些信息可用于限制候选注入

不幸的是,事实并非如此,Spring就是不能这样工作。在分析bean类时,Spring从不从它所在的层次结构往下看。(在其他情况下,我想把方法放在抽象的超类中,并在实现子类上添加
@Transactional
注释,这让我头疼不已。)


因此,如果您需要该功能,您将不得不编写一个Spring核心组件(或它使用的一个助手类)的替换。因为Spring是以模块化的方式设计的,所以只要提供一个子类,就应该能够在不破坏任何东西的情况下完成它。但是如果你不完全需要这个功能,简单的答案是:“它不是那样工作的”:-

我认为你可以在Guice和CDIas中这样做,只要根bean类不是泛型的,容器在所有注入点上都有完整的类型信息。但是通过反射可以得到泛型的类型。但是Spring显然没有使用它。那么也许有解决办法?