Key Takeaways
- @Qualifier is used in Spring Boot to specify which bean should be injected when multiple beans of the same type exist.
- @Primary sets a default bean to use, but @Qualifier takes precedence when both are defined.
- Spring uses @Autowired to inject dependencies automatically, and @Qualifier helps resolve ambiguity when multiple bean candidates exist.
Animal.java
package com.example.demo;
public interface Animal {
public void makeNoise();
}
Cow.java
package com.example.demo;
import org.springframework.stereotype.Component;
@Component("Cow")
public class Cow implements Animal {
public void makeNoise() {
System.out.println("Moo");
}
}
Pig.java
package com.example.demo;
import org.springframework.stereotype.Component;
@Component("Pig")
public class Pig implements Animal {
public void makeNoise() {
System.out.println("Oink");
}
}
Farm.java
package com.example.demo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
public class Farm {
@Autowired
@Qualifier("Pig")
Animal animal;
public Farm(){
}
}
DemoApplication.java
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
}
The @Qualifier annotation helps Spring determine which specific implementation of a bean interface to inject in situations where there are multiple candidates. If you don’t use @Qualifier in the above example, Spring will raise an exception due to confusion about which Animal to inject:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'farm': Unsatisfied dependency expressed through field 'animal'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.example.demo.Animal' available: expected single matching bean but found 2: Cow,Pig
@Qualifier fixes this problem by clearly designating the bean name to be injected, ensuring Spring knows exactly which bean to choose. When two or more beans implement the same interface, @Qualifier specifies which implementation to use.
What is the Use of @Qualifier Annotation in Spring?
@Qualifier is implemented alongside @Autowired to resolve conflicts when multiple beans of the same type are present in the application context. The annotation allows you to uniquely identify the bean you want when variations of the same type exist, simplifying the dependency injection process.
Using @Qualifier to Identify the Bean to Be Used
Let’s revisit our example to see @Qualifier in action:
@Component("Cow")
public class Cow implements Animal {
...
}
@Component("Pig")
public class Pig implements Animal {
...
}
Here, both Cow and Pig are defined as beans managed by Spring. They are declared with the @Component annotation, specifying their unique names that can later be used with @Qualifier:
@Autowired
@Qualifier("Pig")
Animal animal;
This code snippet shows how you can instruct Spring to pick Pig as the bean to inject into the Farm class.
Alternate Approach
An alternative might be directly annotating the classes with @Qualifier:
@Component
@Qualifier("Cow")
public class Cow implements Animal {
...
}
@Component
@Qualifier("Pig")
public class Pig implements Animal {
...
}
This can offer a more organized setup depending on your project structure and preferences.
@Qualifier vs @Primary
While both @Qualifier and @Primary can guide @Autowired in selecting which bean to inject, differences exist:
If we remove @Qualifier from Farm and use @Primary on Pig:
@Component("Pig")
@Primary
public class Pig implements Animal{
public void makeNoise() {
System.out.println("Oink");
}
}
@Primary anchors a default choice unless overridden by a specific @Qualifier specification. Consequently, @Qualifier will always prevail if both annotations are utilized:
- @Primary establishes a default, used when no @Qualifier is present.
- @Qualifier overrides @Primary due to its specificity.
Conclusion
Essentially, the @Qualifier annotation serves as a precise tool in Spring Boot to handle situations where multiple beans of the same type lurk in the application context. Its use is crucial when ambiguity from similar types of beans arises.
Conversely, @Primary provides a catch-all, more general solution where @Qualifier isn't specifically declared. Both serve valid roles depending on your application’s architectural requirements.
In certain contexts, naming conventions can suffice without using @Qualifier, aligning field names with bean names:
@Component
public class Farm {
@Autowired
Animal Pig;
public Farm(){
}
}
This avenue hinges on meticulous use of case sensitivity – aiding simplicity when setups permit.
FAQ
Why would I need to use @Qualifier?
Use @Qualifier when multiple beans of the same type exist, and you need to specify which one should be injected by Spring.
Can @Primary and @Qualifier be used together?
Yes, you can use both. However, @Qualifier will take precedence over @Primary when both are defined.
What happens if I don’t use @Qualifier or @Primary?
If multiple beans of the same type exist and neither @Qualifier nor @Primary is used, Spring will throw an exception due to ambiguity.
Is it case-sensitive when matching bean names with field names?
Yes, it is case-sensitive. The field name must match the bean's component name exactly for Spring to correctly inject it without using @Qualifier.
