11

Occasionally I've noticed interesting thing:

I've implemented spring Converter interface:

@Component
public class MyConverter implements Converter<MyClass1, MyClass2> {

    @Override
    public MyClass2 convert(MyClass1 source) {
       // doesn't matter
    }
}

In controller I autowire it like this

@Autowire
Converter<MyClass1, MyClass2> myConverter;

Surprise but spring inject proper class.

According my information spring autowires beans in runtime. Also I know that in Runtime generic types erasure.

I am tried to understand Spring soure but it hard for me.

Can you explain idea how does spring resolve this situation?

gstackoverflow
  • 36,709
  • 117
  • 359
  • 710

2 Answers2

5

Even though type erasure happens, some of the type-parameter information is not actually erased, but it's rather preserved elsewhere at Runtime.

For this class:

public class MyConverter implements Converter<MyClass1, MyClass2>

the parameterized types for the super-interface (Converter) are preserved, because the JVM should know that the compiled MyConverter implements an abstract method with a signature that actually contains these two types (MyClass1 and MyClass2).

In order to demonstrate this, you can try out the following snippet in a simple main method - here, the parameterized information for the super-interface is restored at Runtime with Reflection:

Type[] interfaces = MyConverter.class.getGenericInterfaces();

ParameterizedType interfaceType = (ParameterizedType) interfaces[0];
Type[] types = interfaceType.getActualTypeArguments();

for (Type argument : types) {
    System.out.println(argument.getTypeName());
}

These Reflection-related classes (Type, ParameterizedType, etc.) are the ones which are actually being used by the Spring's ResovableType class, which is responsible for detecting the best candidate for wiring, based on the provided type-information.

Konstantin Yovkov
  • 62,134
  • 8
  • 100
  • 147
  • I'd like to add that information about type parameters are accessible from the `myConverter` field also (although not from the *value* of the field). That information can be matched against the one from the `MyConverter` class. – Lii Aug 14 '15 at 12:23
2

It is because of what they describe in their blogpost here.

Quote,

Starting with Spring Framework 4.0, Spring will automatically consider generics as a form of @Qualifier. Behind the scenes, the new ResolvableType class provides the logic of actually working with generic types. You can use it yourself to easily navigate and resolve type information.

So the answer is in this class and in this class (and in this class).

EpicPandaForce
  • 79,669
  • 27
  • 256
  • 428
  • 3
    This should be a comment rather then an answer. – Naman Gala Aug 14 '15 at 10:58
  • as you can see in [how to answer](http://stackoverflow.com/help/how-to-answer): *Links to external resources are encouraged, **but please add context around the link so your fellow users will have some idea what it is and why it’s there**. Always quote the most relevant part of an important link, in case the target site is unreachable or goes permanently offline.* – Jordi Castilla Aug 14 '15 at 11:00
  • The Spring Framework Core is actually quite a fascinating place. I should read it more often. – EpicPandaForce Aug 14 '15 at 11:13