spring 容器是否为属于相同泛型 class 但使用不同类型的对象创建新 bean?

Does spring container create new beans for the objects which belong to same generic class but use different types?

如果我在不同控制器中使用不同类型自动装配通用 class,spring 容器会为每个类型创建新实例吗?

假设我有一个通用的 class。

@Component
class MyClass<T, K>{

    public K doStuff(T t){
        // some logic here
    }

}

在我使用的控制器中

@Autowired
MyClass<Employee, Integer> myClass;

我在另一个控制器中使用

@Autowired
MyClass<Manager, String> myClass;

我使用 Spring 5.1.6-RELEASE 对其进行了测试。这是代码和输出:

@Component
public class TestClassWithInteger {

    private MyClass<Integer, Integer> myClass;

    @Autowired
    public TestClassWithInteger(MyClass<Integer, Integer> myClass) {
        this.myClass = myClass;

        this.perform();
    }


    public void perform() {
        System.out.println(myClass);
        myClass.doStuff(1);
    }
}

@Component
public class TestClassWithString {

    private MyClass<String, String> myClass;

    @Autowired
    public TestClassWithString(MyClass<String, String> myClass) {
        this.myClass = myClass;

        this.perform();
    }


    public void perform() {
        System.out.println(myClass);
        myClass.doStuff("test");
    }
}

@Component
class MyClass<T, K>{

    public K doStuff(T t){
        System.out.println(t);
        return null;
    }

}

输出为:

test.example.MyClass@841e575
1
test.example.MyClass@841e575
test

正如您所见,由于默认情况下您的通用 bean 是单例,因此它由应用程序上下文返回 - 请注意打印对象时哈希码的十六进制 - 它是相同的。当我们将 MyClass bean 范围更改为原型时,输出为:

test.example.MyClass@533b266e
1
test.example.MyClass@62679465
test

只要为新 bean 查询应用程序上下文,您就会获得新实例 - 正如预期的那样。

所以问题的答案:

Does spring container create new beans for the objects which belong to same generic class but use different types?

是:不,不是

为了阐明其工作原理,我们可以参考 Phillip Webb 发表的评论 here :

Although erasure happens at the object level, there's a lot of information still in the bytecode. By starting at a field, parameter or return type we can inspect the information that's still there. For example, if you look at java.lang.reflect.Method you'll see that in addition to getReturnType that is a getGenericReturnType method which provides a lot more information. Spring's ResolvableType just tries to make this information easier to access.