I've been struggling a while now with using custom @Qualifier in conjunction with @Bean over the factory method. It looks like this:
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE,
ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface MyCustomQualifierUno {
String value() default "";
}
@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE,
ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface MyCustomQualifierDos {
String value() default "";
}
And the factory class for desired beans consists of the below two methods:
@Bean
@MyCustomQualifierUno
public RestTemplate getRestTemplate(SomeConfigUno config,
SomeErrorHandlerUno errorHandler) {
return new RestTemplateBuilder()
(...)
.build();
}
@Bean
@MyCustomQualifierDos
public RestTemplate getRestTemplate(SomeConfigDos config,
SomeErrorHandlerDos errorHandler) {
return new RestTemplateBuilder()
(...)
.build();
}
Next, in the Client class I have a ctor injection done like this:
public SomeClientUno(@SomeQualifierUno RestTemplate
restTemplate) {
this.restTemplate = restTemplate;
}
public SomeClientDos(@SomeQualifierDos RestTemplate
restTemplate) {
this.restTemplate = restTemplate;
}
When I'm trying to run the app I get: NoSuchBeanDefinitionException
Quite intriguing tough is the fact, that when I add a dedicated class that extends the RestTemplate and placed there my @CustomQualifier I get exception, that there are actually two beans now (i.e. now it does consider the @Bean method)!
Running through: IntelliJ Ultimate 2019.1 OS: Windows 10 64bit Java: 1.8.0_191 Spring version: 5.1.9
PS. Those "Uno's and 'Dos'ses are meant to stress the fact, that those are some concrete types, quite irrelevant, but don't get confused with the "Uno's and 'Dos'ses in the @Qualifiers
This may seem too obvious, but why should you use Qualifiers at all? Let's assume you define your beans like this:
@Bean
public RestTemplate restTemplateUno(...) { ... }
@Bean
public RestTemplate restTemplateDos(...) { ... }
This registers the beans with the qualifiers "restTemplateUno" and "restTemplateDos", because "By default, the bean name will be the same as the method name" (see Spring Docs for details).
You could now inject them in the client constructors like this:
@Autowired
public SomeClientUno(RestTemplate restTemplateUno) {...}
@Autowired
public SomeClientDos(RestTemplate restTemplateDos) {...}
I hope this helps and I didn't miss something obvious that caused you to consider using Qualifiers in the first place.