Autowiring based on generic types in Spring. How does it work?
Erasure means that the information is gone from the runtime. It's still there in the compile-time information, which you can access through reflection. At a rough level, you can think of it that generic information about individual instances is erased, but generic information about classes is not.
For instance, here's a simple program that defines a generic method foo
and then prints out the generic information about it from main
:
import java.util.*;import java.lang.reflect.*;public class GenericReflection { public static void main(String[] args) throws Exception { Method m = GenericReflection.class.getDeclaredMethod("foo"); System.out.println(m.getGenericReturnType()); } public static List<String> foo() { return null; }}
Output:
java.util.List<java.lang.String>
As you can see, it's not too complex when you get down to it.
Method.getGenreicReturnType
returns a java.lang.reflect.Type
, which has a few subclasses. One is ParameterizedType
, which has a method getActualTypeArguments
that returns the actual types that this type is parameterized to. Those types might also be generic, of course, which is why it returns a Type[]
and not Class[]
. In the foo
example above, it'd return an array with one element, representing String
:
ParameterizedType pm = (ParameterizedType) m.getGenericReturnType();Type[] pmArgs = pm.getActualTypeArguments();System.out.println(Arrays.toString(pmArgs));
[class java.lang.String]
There are similar "generic" methods for Field.getGenericType
. You can use this information to find out that List<String>
is a List
parameterized to String
, which is exactly the information they need.