As you know, there is a new feature in Spring 4: autowiring based on generic types. It's very useful, but I wonder, how Spring developers were able to bypass type erasure, which had prevented them to develop such feature before.
The Spring framework enables automatic dependency injection. In other words, by declaring all the bean dependencies in a Spring configuration file, Spring container can autowire relationships between collaborating beans. This is called Spring bean autowiring.
Autowiring by autodetect uses either of two modes i.e. constructor or byType modes. First it will try to look for valid constructor with arguments, If found the constructor mode is chosen. If there is no constructor defined in bean, or explicit default no-args constructor is present, the autowire byType mode is chosen.
Autowiring 'byName':This option enables autowire based on bean names. Spring looks up the configuration file for a matching bean name. If found, this bean is injected in the property. However, if no such bean is found, an error is raised.
Autowiring feature of spring framework enables you to inject the object dependency implicitly. It internally uses setter or constructor injection. Autowiring can't be used to inject primitive and string values. It works with reference only.
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.
The most important details are in this article from the Spring Blog.
As you can see, all the magic is hidden inside the ResolvableType
class whose Javadoc you can find here and its code can be found here (it's a pretty heavy reading :))
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