Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Autowire Bean of generic type <T> in Spring?

I have a bean Item<T> which is required to be autowired in a @Configuration class.

@Configuration public class AppConfig {      @Bean     public Item<String> stringItem() {         return new StringItem();     }      @Bean     public Item<Integer> integerItem() {         return new IntegerItem();     }  } 

But when I try to @Autowire Item<String>, I get following exception.

"No qualifying bean of type [Item] is defined: expected single matching bean but found 2: stringItem, integerItem" 

How should I Autowire generic type Item<T> in Spring?

like image 226
user3374518 Avatar asked Mar 24 '14 07:03

user3374518


People also ask

Can you Autowire by type?

This mode specifies autowiring by property type. Spring container looks at the beans on which autowire attribute is set to byType in the XML configuration file. It then tries to match and wire a property if its type matches with exactly one of the beans name in the configuration file.

What is difference between @bean and @autowire?

@Bean is just for the metadata definition to create the bean(equivalent to tag). @Autowired is to inject the dependancy into a bean(equivalent to ref XML tag/attribute).

What is difference between @autowired and @resource in Spring?

The main difference is is that @Autowired is a spring annotation whereas @Resource is specified by the JSR-250. So the latter is part of normal java where as @Autowired is only available by spring.

What is T in generics in Java?

< T > is a conventional letter that stands for "Type", and it refers to the concept of Generics in Java. You can use any letter, but you'll see that 'T' is widely preferred. WHAT DOES GENERIC MEAN? Generic is a way to parameterize a class, method, or interface.


1 Answers

Simple solution is to upgrade to Spring 4.0 as it will automatically consider generics as a form of @Qualifier, as below:

@Autowired private Item<String> strItem; // Injects the stringItem bean  @Autowired private Item<Integer> intItem; // Injects the integerItem bean 

Infact, you can even autowire nested generics when injecting into a list, as below:

// Inject all Item beans as long as they have an <Integer> generic // Item<String> beans will not appear in this list @Autowired private List<Item<Integer>> intItems; 

How this Works?

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. Most methods on ResolvableType will themselves return a ResolvableType, for example:

// Assuming 'field' refers to 'intItems' above ResolvableType t1 = ResolvableType.forField(field); // List<Item<Integer>>  ResolvableType t2 = t1.getGeneric(); // Item<Integer> ResolvableType t3 = t2.getGeneric(); // Integer Class<?> c = t3.resolve(); // Integer.class  // or more succinctly Class<?> c = ResolvableType.forField(field).resolveGeneric(0, 0); 

Check out the Examples & Tutorials at below links.

  • Spring Framework 4.0 and Java Generics
  • Spring and Autowiring of Generic Types

Hope this helps you.

like image 105
Shishir Kumar Avatar answered Sep 29 '22 11:09

Shishir Kumar