@Qualifier Annotation

In this article of Spring Boot, we will look at the @Qualifier annotation in Spring. We will see how to use this Spring annotation and when we should use it. 

 

Introduction

The @Autowired annotation is the most used way to inject the dependencies in Spring. By default, the @Autowired resolve dependencies by type. This works fine until we have only one bean with the same type. Spring framework will throw an exception if over one bean with the same type is available with the container. The @Autowired annotation will not work in this case.Let’s see this simple example for clarity:

@Service("userServiceImpl")
public class UserServiceImpl implements UserService {
    @Override
    public void enableUser() { }
}
@Service("defaultUserService")
public class DefaultUserService implements UserService {

  @Override
  public void enableUser() {}
}
public class OrderFacade {
  
  @Autowired
  private UserService userService;
}

If we run this code, we may see the following exception on application startup

Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'orderController': Unsatisfied dependency expressed through field 'orderFacade'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: 
Error creating bean with name 'orderFacade': Unsatisfied dependency expressed through field 'userService'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: 
No qualifying bean of type 'com.javadevjournal.rest.service.UserService' available: expected single matching bean but found 2: defaultUserService,userServiceImpl

 

1.  @Qualifier Annotation

The @Qualifier annotation helps disambiguate bean references when Spring otherwise could not do so. In our case, to we can use the @Qualifier annotation help in the issue to choose the correct bean for the dependency injection. Let’s change our previous example:

public class OrderFacade {

  @Qualifier("userServiceImpl")
  @Autowired
  private UserService userService;
}

If we run our application again, it will start with no issue. Let’s revisit few important points for clarity:

  1. In new example, we specify the name of the bean along with the @Qualifier. This helps spring to avoid ambiguity when it finds multiple beans of the same type.
  2. Remember to use the bean name as defined in the @Servive annotation (You can use other annotation like @Component).

 

2. @Qualifier vs Autowiring by Name

If you still want to use the @Autowire annotation, there is another way to handle multiple beans when autowiring. Spring framework uses bean name as the default qualifier value. This is the default in case there are no other hints for Spring. Let’s change our previous example to see it in Action:

@Service("userService")
public class UserServiceImpl implements UserService {
    @Override
    public void enableUser() { }
}
@Service("defaultUserService")
public class DefaultUserService implements UserService {

  @Override
  public void enableUser() {}
}
public class OrderFacade {
  
  @Autowired
  private UserService userService;
}

Here, Spring will inject the UserServiceImpl as the dependency on our OrderFacade class:

 

Summary

In this quick post, we saw the @Qualifier annotation in Spring. We learned how qualifier annotation helps disambiguate bean references. In the last part of our article, we saw how to use the @Autowire annotation to inject bean by name.