I have read that @Qualifier can be used in Injection phase whereas @Primary is used in Configuration phase. Am still unclear when to use which.
Also I have below doubts
can @Primary and @Qualifier be used together? if yes does @Qualifier take precedence?
can @Primary be used with @Autowired?
How is the Injection phase different from Configuration phase, this in respect to Spring beans
It's worth noting that if both the @Qualifier and @Primary annotations are present, then the @Qualifier annotation will have precedence. Basically, @Primary defines a default, while @Qualifier is very specific.
One of the most important annotations in spring is @Qualifier annotation which is used to eliminate the issue of which bean needs to be injected.
@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.
So if @Autowired is used together with @Qualifier , it is the same as the @Resource . The difference are that @Autowired and @Qualifier are the spring annotation while @Resource is the standard java annotation (from JSR-250) .
@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".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With