【问题标题】:Spring Problem with generic types泛型类型的Spring问题
【发布时间】:2011-07-28 10:00:25
【问题描述】:

我在使用泛型时遇到了 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());
    }
}

问题是,在 BaseTest 类中应该注入 First 类,因为它具有泛型类型 String。但是 spring 不明白这一点并告诉我,自动装配有两种可能的候选者。原因是 spring 忽略了泛型。是否有解决方案或解决方法?

【问题讨论】:

标签: java spring generics


【解决方案1】:

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

不幸的是,事实并非如此,Spring 不能那样工作。在分析 bean 类时,Spring 从不向下查看它所在的层次结构。 (在我想将方法​​放在抽象超类中并在实现子类上添加 @Transactional 注释的其他情况下,我已经对此表示反对。)

因此,如果您需要该功能,则必须为 Spring 的核心组件之一(AutowiredAnnotationBeanPostProcessor 或它使用的辅助类之一)编写替代品。由于 Spring 是以模块化方式设计的,因此如果您只提供一个子类,您应该能够在不破坏任何内容的情况下做到这一点。但是如果你不是绝对需要这个功能,简单的答案是:“它不能那样工作”:-)

【讨论】:

    【解决方案2】:

    这是由于类型擦除造成的。见:

    http://download.oracle.com/javase/tutorial/java/generics/erasure.html

    When a generic type is instantiated, the compiler translates those types by a technique called type erasure — a process where the compiler removes all information related to type parameters and type arguments within a class or method. Type erasure enables Java applications that use generics to maintain binary compatibility with Java libraries and applications that were created before generics.

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

    【讨论】:

    • 只要根 bean 类不是泛型的,容器就拥有所有注入点的完整类型信息。
    • 但是通过反射可以获得泛型的类型。但是 Spring 显然没有使用它。那么也许有一个解决方法?
    猜你喜欢
    • 1970-01-01
    • 2011-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多