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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With