Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 184 Vote(s) - 3.69 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to Autowire Bean of generic type <T> in Spring?

#1
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?
Reply

#2
If you dont want to upgrade to Spring 4 you have to autowire by name as below :

@Autowired
@Qualifier("stringItem")
private Item<String> strItem; // Injects the stringItem bean

@Autowired
@Qualifier("integerItem")
private Item<Integer> intItem; // Injects the integerItem bean
Reply

#3
Spring 4.0 is the answer with the @Qualifier annotation usage. Hope this helps
Reply

#4
Spring autowired strategy is defined in your configration file(application.xml).

if you don't defined, default is by Type, spring inject use JDK reflect mechanism.

so List?String? and List?Item?, the type is same List.class, so spring confused how to inject.

and as above persons response, you should be point @Qualifier to tell spring which bean should be inject.

i like spring configration file to define bean rather then Annotation.

<bean>
<property name="stringItem">
<list>
<....>
</list>
</property>
</bean>
Reply

#5
I believe it has nothing to with generics... If you are injecting two different beans of same type then you need to provide a qualifier to help Spring identify them;

... Elsewhere

@Configuration
@Bean
public Item stringItem() {
return new StringItem();
}

@Bean
public Item integerItem() {
return new IntegerItem();
}


If you have a non-generic declarations like these then you need to add qualifier to help Spring identify them...

@Autowired
**@Qualifier("stringItem")**
private Item item1;

@Autowired
**@Qualifier("integerItem")**
private Item item2;


Of course, in versions 4 and above spring considers the Generic Types through the resolvers which is very cool...
Reply

#6
Below is a solution I made to answer this question:

```

List<String> listItem= new ArrayList<>();

ResolvableType resolvableType = ResolvableType.forClassWithGenerics(List.class, String.class);
RootBeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setTargetType(resolvableType);
beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
beanDefinition.setAutowireCandidate(true);

DefaultListableBeanFactory bf = (DefaultListableBeanFactory) configurableWebApplicationContext.getBeanFactory();

bf.registerBeanDefinition("your bean name", beanDefinition);
bf.registerSingleton("your bean name", listItem);
```
Reply

#7
Simple solution is to upgrade to [Spring 4.0][1] 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`][2] 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][3]
- [Spring and Autowiring of Generic Types][4]


[1]:

[To see links please register here]

[2]:

[To see links please register here]

[3]:

[To see links please register here]

[4]:

[To see links please register here]

Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through