Spring 4 - @Qualifier annotation example

Posted on February 19, 2017


Technologies used:   JDK 1.8.0_121 | Spring 4.3.5.RELEASE | Maven 3.3.9 | Eclipse Mars.2 (4.5.2)

The @Qualifier annotation is used to resolve the autowiring conflict, when there are multiple beans of same type.

The @Qualifier annotation can be used on any class annotated with @Component or on method annotated with @Bean. This annotation can also be applied on constructor arguments or method parameters.

In this post, we will show you how the @Qualifier annotation is used in the Spring application.

Consider the following Vehicle interface.

Vehicle.java

package com.boraji.tutorial.spring.bean;

public interface Vehicle {

   public void start();

   public void stop();
}

Create two beans named as Car and Bike, which implement Vehicle interface as follows.

Car.java

package com.boraji.tutorial.spring.bean;

import org.springframework.stereotype.Component;

@Component
public class Car implements Vehicle {

   @Override
   public void start() {
      System.out.println("Car started");
   }

   @Override
   public void stop() {
      System.out.println("Car stopped");
   }

}

Bike.java

package com.boraji.tutorial.spring.bean;

import org.springframework.stereotype.Component;

@Component
public class Bike implements Vehicle{

   @Override
   public void start() {
      System.out.println("Bike started");
   }

   @Override
   public void stop() {
      System.out.println("Bike stopped");
   }
}

Create a VehicleService bean, in which the Vehicle will be injected via @Autowire annotation as follows.

VehicleService.java

package com.boraji.tutorial.spring.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.boraji.tutorial.spring.bean.Vehicle;

@Component
public class VehicleService {

   @Autowired
   private Vehicle vehicle;

   public void service() {
      vehicle.start();
      vehicle.stop();
   }
}

 

Now create a main class and run application.

MainApp.java

package com.boraji.tutorial.spring;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.boraji.tutorial.spring.service.VehicleService;

public class MainApp {
   public static void main(String[] args) {
      AnnotationConfigApplicationContext context = 
            new AnnotationConfigApplicationContext();

      // Scan beans
      context.scan("com.boraji.tutorial.spring.bean");
      context.scan("com.boraji.tutorial.spring.service");
      context.refresh();

      VehicleService vehicle = context.getBean(VehicleService.class);
      vehicle.service();

      context.close();
   }
}

Output

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.boraji.tutorial.spring.bean.Vehicle' available: expected single matching bean but found 2: bike,car
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:172)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1114)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1064)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
	... 13 more

As you can see in the above exception, there are two candidates (Car and Bike) for Vehicle annotated with @Autowire in the VehicleService bean. The Spring IoC container unable to determine which bean should be injected and throws an exception NoUniqueBeanDefinitionException.

To fix the above problem, we will use the @Qualifier annotation with class annotated with @Component and field annotated with @Autowired.

Modify the BikeCar and VehicleService beans as follow.

Car.java

@Component
@Qualifier("carBean")
public class Car implements Vehicle {

   //...
   //...
}

Bike.java

@Component
@Qualifier("bikeBean")
public class Bike implements Vehicle{

   //...
   //...
}

VehicleService.java

@Component
public class VehicleService {

   @Autowired
   @Qualifier("carBean")
   private Vehicle vehicle;

   //...
   //...
}

Now run the MainApp class again and see output.

Output

Car started
Car stopped

 

Download Sources