Spring : Difference between @Autowired, @Inject and @Resource

Points To Remember


  • @Inject is not a spring feature you need to include javax inject dependency in order to use @Inject.
  • @Autowired is Spring annotation used to inject dependency just like @Inject. It use @Qualifier annotation to differentiate between the beans.
  • @Resource is also Spring annotation, but it uses bean name to inject dependencies and differentiate between beans.

Problem Statement :: Structure

In order to show how @Autowired @Inject and @Resource annotations work  we will create 3 services

  • Interface PersonService, this is the interface for all person related operations.
  • Class EngineerService, this is the service that will do operations for engineer.
  • Class ManagerService, this is the service that will do operations for manager.
Here, both EngineerService and ManagerService implements PersonService. Now we will try to add the services to a controller by different  ways to test how @Autowire, @Inject and @Resource will work.

So the above structure looks like as shown in the code below.
  1. public interface PersonService {  
  2.   
  3.     public String getName();  
  4. }  
  5.   
  6.   
  7. @Service  
  8. public class EngineerService implements PersonService {  
  9.   
  10.     @Override  
  11.     public String getName() {  
  12.         return "EngineerService";  
  13.     }  
  14.   
  15. }  
  16.   
  17. @Service  
  18. public class ManagerService implements PersonService {  
  19.   
  20.     @Override  
  21.     public String getName() {  
  22.         return "ManagerService";  
  23.     }  
  24. }  

Test with @Autowired annotations

  1. Parent Reference Type and name

    1. @RestController  
    2. public class PersonController {  
    3.   
    4.     @Autowired  
    5.     private PersonService personService;  
    6.   
    7.     @Resource  
    8.     private PersonService personService;  
    9.   
    10.     @Inject  
    11.     private PersonService personService;  
    12. }  
    In this case @Autowired @Inject and @Resource all will throw the following exception.
    Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException

  2. Parent Reference Type and Child Reference Name

    1. @RestController  
    2. public class PersonController {  
    3.   
    4.     @Autowired  
    5.     private PersonService engineerService;  
    6.   
    7.     @Resource  
    8.     private PersonService engineerService;  
    9.   
    10.     @Inject  
    11.     private PersonService engineerService;  
    12.   
    13. }  
    In this case, all @Autowired, @Inject and @Resource annotations will inject EngineerService, and getName() will return "EngineerService".
    Note :: When beans are created, they are created by name of the class, EngineerService will resolve to engineerService and its bean will be resolved by name engineerService. Hence when we try to use it with PersonService engineerService , this will inject engineerService bean.
    1. public interface PersonService {  
    2.   
    3.     public String getName();  
    4. }  
    5.   
    6. @Service  
    7. @Qualifier(value = "engineer")  
    8. public class EngineerService implements PersonService {  
    9.   
    10.     @Override  
    11.     public String getName() {  
    12.         return "EngineerService";  
    13.     }  
    14.   
    15. }  
    16.   
    17. @Service  
    18. @Qualifier(value = "manager")  
    19. public class ManagerService implements PersonService {  
    20.   
    21.     @Override  
    22.     public String getName() {  
    23.         return "ManagerService";  
    24.     }  
    25. }  
    26.   
    27. @RestController  
    28. public class PersonController {  
    29.   
    30.     @Autowired  
    31.     @Qualifier(value = "engineer")  
    32.     private PersonService personService;  
    33.   
    34.     @Resource  
    35.     @Qualifier(value = "engineer")  
    36.     private PersonService personService;  
    37.   
    38.     @Inject  
    39.     @Qualifier(value = "engineer")  
    40.     private PersonService personService;  
    41.   
    42. }  
    In this case, all will inject the EngineerService bean to the PersonCOntroller. This is because we have given names to beans using @Qualifier annotation and then used them with the same name.
  3. Ambiguous Qualifiers with Parent Reference Type and name

    1. public interface PersonService {  
    2.   
    3.     public String getName();  
    4. }  
    5.   
    6. @Service  
    7. @Qualifier(value = "person")  
    8. public class EngineerService implements PersonService {  
    9.   
    10.     @Override  
    11.     public String getName() {  
    12.         return "EngineerService";  
    13.     }  
    14.   
    15. }  
    16.   
    17. @Service  
    18. @Qualifier(value = "person")  
    19. public class ManagerService implements PersonService {  
    20.   
    21.     @Override  
    22.     public String getName() {  
    23.         return "ManagerService";  
    24.     }  
    25. }  
    26.   
    27. @RestController  
    28. public class PersonController {  
    29.   
    30.     @Autowired  
    31.     @Qualifier(value = "person")  
    32.     private PersonService personService;  
    33.   
    34.     @Resource  
    35.     @Qualifier(value = "person")  
    36.     private PersonService personService;  
    37.   
    38.     @Inject  
    39.     @Qualifier(value = "person")  
    40.     private PersonService personService;  
    41.   
    42. }  
    In this case, since the qualifiers are ambiguous, all the three will result in the exception.
    Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException

    This is because spring will not be able to find a unique bean with the qualifier "person".
  4. Ambiguous Qualifiers with Parent Reference type and Child Reference name

    1. public interface PersonService {  
    2.   
    3.     public String getName();  
    4. }  
    5.   
    6. @Service  
    7. @Qualifier(value = "engineer")  
    8. public class EngineerService implements PersonService {  
    9.   
    10.     @Override  
    11.     public String getName() {  
    12.         return "EngineerService";  
    13.     }  
    14.   
    15. }  
    16.   
    17. @Service  
    18. @Qualifier(value = "manager")  
    19. public class ManagerService implements PersonService {  
    20.   
    21.     @Override  
    22.     public String getName() {  
    23.         return "ManagerService";  
    24.     }  
    25. }  
    26.   
    27. @RestController  
    28. public class PersonController {  
    29.   
    30.     @Autowired  
    31.     @Qualifier(value = "engineer")  
    32.     private PersonService engineerService;  
    33.   
    34.     @Resource  
    35.     @Qualifier(value = "engineer")  
    36.     private PersonService engineerService;  
    37.   
    38.     @Inject  
    39.     @Qualifier(value = "engineer")  
    40.     private PersonService engineerService;  
    41.   
    42. }  
    In this case, @Autowired and @Inject will throw the following exception
    Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException
    But, @Resouce will still inject the EngineerService bean.


Hence following conclusion can be made on the basis of the above test scenario's

  • All, @Autowired, @Inject and @Resource throws exception with Ambiguous Bean names.
  • If Unique Qualifiers are used, all will inject the specified beans.
  • If Ambiguous beans are there only @Resouce can inject beans based on names of Bean name.

No comments:

Powered by Blogger.