I have two implementations for one interface, i want to choose what implementation to use based on a configuration. The qualifier solution did not work as it is initialized prior to the configuration. How can I achieve this?
-
does it work without the qualifier? – Jose Martinez Aug 06 '19 at 12:21
-
Could you please describe your use-case? Qualifiers are used when there are more than one bean of the same type co-exist in Application context and you want to inject a particular bean. In this case no need for dynamic configuration usually, you chose among a set of predefined values for injecting the bean with qualifier – Mark Bramnik Aug 06 '19 at 12:24
-
@JoseMartinez Without it, i will have to add constructor dependencies manually, which is not nice in a spring project – user666 Aug 06 '19 at 12:26
-
@MarkBramnik I have two different implementations of a job and it is possible to change the type every month so if configurable, less deployments and code changes are made. – user666 Aug 06 '19 at 12:27
-
Possible duplicate of [How to read Qualifier from property file in spring boot?](https://stackoverflow.com/questions/50208018/how-to-read-qualifier-from-property-file-in-spring-boot) – Andy Brown Aug 07 '19 at 07:54
5 Answers
I've got your comment:
I have two different implementations of a job and it is possible to change the type every month so if configurable, less deployments and code changes are made.
You might have something like this:
interface Job {
void foo();
}
class JobA implements Job {
void foo() {...}
}
class JobB implements Job {
void foo() {...}
}
class JobExecutor {
Job job;
// autowired constructor
public JobExecutor(Job job) {this.job = job;}
}
And, if I got you right, it doesn't make sense to load two beans simultaneously in the same application context.
But if so, then @Qualifier
is not a right tool for the job.
I suggest using conditions that are integrated into spring boot instead:
@Configuration
public class MyConfiguration {
@ConditionalOnProperty(name = "job.name", havingValue = "jobA")
@Bean
public Job jobA() {
return new JobA();
}
@ConditionalOnProperty(name = "job.name", havingValue = "jobB")
@Bean
public Job jobB() {
return new JobB();
}
@Bean
public JobExecutor jobExecutor(Job job) {
return new JobExecutor(job);
}
}
Now in application.properties
(or yaml whatever you have) define:
job.name = jobA # or jobB
Of course, instead of jobA/jobB
you might use more self-explanatory names from your business domain.

- 39,963
- 4
- 57
- 97
You could pull it off with if you fiddle around with Spring java-based config a bit, where you programmatically decide the right implementation based on a config value:
@Configuration
public class MyAppContext implements EnvironmentAware{
private Environment env;
@Override
public void setEnvironment(final Environment env) {
this.env = env;
}
@Bean
public MyBeanByConfig myBeanByConfig(){
String configValue = env.getProperty("mybean.config");
if(configValue.equals("1")){
return new MyBeanByConfigOne();
}else{
return new MyBeanByConfigTwo();
}
}
}
and on the qualifier you would put:
@Qualifier("myBeanByConfig")
you may need to add @ComponentScan
and @PropertySource
on the configuration class also.

- 25,605
- 12
- 54
- 63
I ended up adding to the main app class the two implementations autowired then define a bean for each:
@Autowired
TypeOneImpl typeOneImpl
@Bean(name = "typeOneImpl")
public InterfaceRClass getTypeOneImpl()
{
return typeOneImpl;
}
Then in the other class I defined a config field
@Value("${myClass.type}")
private String configClassType;
// the below should be defined in constructor
private final InterfaceRClass interfaceRClassElement ;
And added a setter for it with @Autowired annotation:
@Autowired
public void setMyClassType(ApplicationContext context) {
interfaceRClassElement = (InterfaceRClass) context.getBean(configClassType);
}
In configuration, the value should be typeOneImpl (typeTwoImpl is added for an additional implementation)

- 1,750
- 3
- 18
- 34
Let's suppose you have an interface:
public interface Foo {
void doSomething();
}
And 2 implementations:
public class Foo_A implements Foo {
@Override
doSomething() {...}
}
public class Foo_B implements Foo {
@Override
doSomething() {...}
}
Now you want to use Foo_A/Foo_B depending on a property value in your properties file:
foo_name: "A"
The simplest way I found to do this:
- First, you qualify your implementations
@Component("Foo_A")
public class Foo_A implements Foo {
@Override
doSomething() {...}
}
@Component("Foo_B")
public class Foo_B implements Foo {
@Override
doSomething() {...}
}
- Then, wherever you gonna use this (class Bar, for example), you can just use the @Qualifier to specify the implementations you are instantiating and get the value from the property with the @Value. Then, inside the method, with a simple if/else statement, you use the property value to decide which implementation you're going to call.
public class Bar {
@Value("${foo_name}")
private String fooName;
@Qualifier("Foo_A")
private Foo fooA;
@Qualifier("Foo_B")
private Foo fooB;
public void doSomething() {
if (fooName.equals("A")) {
fooA.doSomething();
} else {
fooB.doSomething();
}
}
}

- 85
- 3
knowing that IOC works fine throught constructor maybe I would do something like this:
@Component
public class JobExecutor implements WhateverService {
private final Job myJob;
public JobExecutor(Map<String, Job> allJobImpls,
@Value("${myClass.type}") final String classType) {
this.myJob = allImpls.get(classType);
}
public X myAction() {
// some code
return myJob.whatever(); //for example
}
}

- 57,590
- 26
- 140
- 166

- 21
- 6