Search code examples
javaspringgenericsinversion-of-control

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


If i autowire my generic class with different types in different controllers, does spring container create new instance for each?

Assume i have a generic class.

@Component
class MyClass<T, K>{

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

}

In a controller i use

@Autowired
MyClass<Employee, Integer> myClass;

and in another controller i use

@Autowired
MyClass<Manager, String> myClass;

Solution

  • I made a test for it using Spring 5.1.6-RELEASE . Here is the code and output :

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

    The output is :

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

    So as you can see, because of the fact that your generic bean is a singleton by default, it is returned by the application context - notice the hex of hashcode when printing the object - it is the same. When we change MyClass bean scope to prototype then the output is :

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

    you get new instance whenever application context is queried for a new bean - as expected.

    So the answer for the question :

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

    is : No, it does not.

    And to shed some light on how it works we can refer to Phillip Webb's comment posted 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.