When to use Qualifier and Primary in Spring
Solution 1:
@Primary
indicates that a bean should be given preference when multiple candidates
are qualified to autowire a single-valued dependency.
@Qualifier
indicates specific bean should be autowired when there are multiple candidates.
For example, we have two beans both implement the same interface.
public interface BeanInterface {
String getName();
}
public class Bean1 implements BeanInterface {
@Override
public String getName() {
return "bean 1";
}
}
public class Bean2 implements BeanInterface {
@Override
public String getName() {
return "bean2";
}
}
Here is our service.
@Service
public class BeanService {
@Autowired
private BeanInterface bean;
}
And our configuration.
@Configuration
public class Config {
@Bean("bean1")
public BeanInterface bean1() {
return new Bean1();
}
@Bean("bean2")
public BeanInterface bean2() {
return new Bean2();
}
}
When Spring starts, it will find there are two beans("bean1" and "bean2") both can be autowired to BeanService
since they implement the same interface BeanInterface
. It reports an error in my Idea.
Could not autowire. There is more than one bean of 'BeanInterface' type.
Beans: bean1 (Config.java)
bean2 (Config.java)
And without a hint, Spring does not know which one to use.
So in our case, when we add @Primary
to Config.bean1()
.
@Bean("bean1")
@Primary
public BeanInterface bean1() {
return new Bean1();
}
It tells Spring, "when you find more than one beans that both can be autowired, please use the primary one as your first choose." So, Spring will pick bean1
to autowire to BeanService
.
Here is another way to autowire bean1
to BeanService
by using @Qualifier
in BeanService.class
.
@Service
public class BeanService {
@Autowired
@Qualifier("bean1")
private BeanInterface bean;
}
@Qualifier
will tell Spring, "no matter how many beans you've found, just use the one I tell you."
So you can find both @Qualifier
and @Primary
are telling Spring to use the specific bean when multiple candidates are qualified to autowire. But @Qualifier
is more specific and has high priority. So when both @Qualifier
and @Primary
are found, @Primary
will be ignored.
Here is the test.
@Configuration
public class Config {
@Bean("bean1")
@Primary
public BeanInterface bean1() {
return new Bean1();
}
@Bean("bean2")
public BeanInterface bean2() {
return new Bean2();
}
}
@Service
public class BeanService {
@Autowired
@Qualifier("bean2")
private BeanInterface bean;
@PostConstruct
public void test() {
String name = bean.getName();
System.out.println(name);
}
}
The output is "bean2".
Solution 2:
Also, need to remember that @Qualifier
as bigger priority then @Primary
, that's means that it's waste to define both of the annotations.
@Primary
means default implementation, while @Qualifier
is the specific implementation.
You can review my blog I wrote regarding this annotations - http://shaikezam.com/spring_qualifier