@Qualifier Annotation in Spring
March 20, 2022
This page will walk through Spring @Qualifier
annotation example.
1. The
@Qualifier
may be used on a field or parameter as a qualifier for candidate beans when autowiring.
2. In the scenario where more than one beans are eligible to be autowired, we use
@Qualifier
annotation.
3. The same scenario can also be handled by
@Primary
annotation. The @Qualifier
defines more robust selection criteria than @Primary
annotation.
4. We can also use
@Qualifier
to create custom qualifier annotation.
Contents
@Qualifier at Field level
Here we are using@Qualifier
at field level.
@Service public class AnimalService { @Autowired @Qualifier("fox") private Animal animal; public Animal getAnimal() { return animal; } ------ }
Find the other files of our demo.
Animal.java
package com.concretepage; public interface Animal { void printName(); }
package com.concretepage; import org.springframework.stereotype.Component; @Component("deer") public class Deer implements Animal { @Override public void printName() { System.out.println("I am Deer"); } }
package com.concretepage; import org.springframework.stereotype.Component; @Component("fox") public class Fox implements Animal { @Override public void printName() { System.out.println("I am Fox"); } }
package com.concretepage; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; @Service public class AnimalService { @Autowired @Qualifier("deer") private Animal animal; public Animal getAnimal() { return animal; } }
@Component
as @Component("fox")
, then fox becomes the bean name.
We can see that
Fox
and Deer
both components are the implementations of Animal
interface. In AnimalService
class, we have autowired the animal property for which two beans are eligible to be injected i.e. fox and deer.
Case-1: When we write the code as below.
@Autowired private Animal animal;
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.concretepage.Animal] is defined: expected single matching bean but found 2: deer,fox
@Qualifier
annotation.
@Autowired @Qualifier("deer") private Animal animal;
Deer
component will be injected.
Now run the code.
SpringDemo.java
package com.concretepage; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class SpringDemo { public static void main(String[] args) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); ctx.register(AppConfig.class); ctx.refresh(); AnimalService animal = ctx.getBean(AnimalService.class); animal.getAnimal().printName(); } }
I am Deer
@Qualifier at Parameter level
Here we are using@Qualifier
at parameter level.
@Service public class AnimalService { @Autowired public AnimalService(@Qualifier("deer") Animal animal){ this.animal = animal; } ------ }
@Qualifier vs @Primary
For the case when more than one beans are eligible to be autowired, we can also use@Primary
annotation. The @Primary
annotation is used to make a bean preferable when multiple beans are qualified to autowire a single-valued dependency.
Find the example to use
@Primary
.
@Component("fox") @Primary public class Fox implements Animal { ------ }
Animal
property of a class.
@Autowired private Animal animal;
To inject deer bean, specify it by using
@Qualifier
annotation.
@Autowired @Qualifier("deer") private Animal animal;
Autowire byName
To handle the scenario where more than one beans are eligible to be autowired, we can also use the XML<bean>
with byName configuration. The byName is a value of autowire
property of XML <bean>
element. If there are more than one beans of same class with different bean names in our XML configuration, then with the use of byName, the autowiring will not conflict and take the matching bean name with class property name.
<bean name="employee" class="com.concretepage.Employee" autowire="byName"> <property name="empName" value="Mahesh"/> </bean> <bean name="permanentAddress" class="com.concretepage.Address"> <property name="city" value="Varanasi"/> <property name="state" value="Uttar Pradesh"/> </bean> <bean name="localAddress" class="com.concretepage.Address"> <property name="city" value="Bhopal"/> <property name="state" value="Madhya Pradesh"/> </bean>
@Autowired
annotation.
public class Employee { @Autowired private Address localAddress; ------ }
Address
class type, localAddress and permanentAddress. The Employee
class has an autowired property and this will be injected with matching bean name that is localAddress.