Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Autowiring based on generic types in Spring. How does it work?

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.

like image 988
Patison Avatar asked Jun 30 '14 12:06

Patison


People also ask

How does Autowiring in spring work?

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.

How the Auto Detect Autowiring internally works?

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.

Does spring Autowire by name or type?

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.

What is Autowiring in spring and its types?

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.


2 Answers

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.

like image 129
yshavit Avatar answered Nov 09 '22 19:11

yshavit


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 :))

like image 39
geoand Avatar answered Nov 09 '22 18:11

geoand