@Autowired vs @Inject vs @Resource

We can use @Autowired or @Inject or @Resource annotations for injecting dependencies in the Spring Beans

  • @Resource – Defined in the javax.annotation package and this annotation is part of the JSR-250 annotation collection and is packaged with Java EE.
  • @Inject – Defined in the javax.inject package.In order to access the @Inject annotation, the javax.inject library has to be declared as a Maven dependency.
  • @Autowired – Defined in the package org.springframework.bean.factory and part of Spring framework.

@Autowired and @Inject annotation behave identically. These two annotations use AutowiredAnnotationBeanPostProcessor to inject dependencies.

@Resource uses CommonAnnotationBeanPostProcessor to inject dependencies.

Order of Execution

@Autowired and @Inject

  1. Matches by Type
  2. Restricts by Qualifiers
  3. Matches by Name

@Resource

  1. Matches by Name
  2. Matches by Type
  3. Restricts by Qualifiers (ignored if match is found by name)

Let us see how these annotations work in the below example.

Here, we have Animal interface and two implementations Tiger and Lion.

package com.spring.example.bean;

public interface Animal {

String type();

}

package com.spring.example.bean;

import org.springframework.stereotype.Component;

@Component
public class Tiger implements Animal{

@Override
public String type() {
return “Tiger”;
}

}

package com.spring.example.bean;

import org.springframework.stereotype.Component;

@Component
public class Lion implements Animal{

@Override
public String type() {
return “Lion”;
}

}

Scenario 1 : Inject using Interface type – Using @Resource or @Inject or @Autowired

package com.spring.example.bean;

import javax.annotation.Resource;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;

import com.spring.example.config.BeanConfiguration;

@Component
public class AnimalKeeper {

@Resource
private Animal animal;
//
// @Inject
// private Animal animal;
//
// @Autowired
// private Animal animal;

public Animal getAnimal() {
return animal;
}

public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(BeanConfiguration.class);
AnimalKeeper animalKeeper = context.getBean(AnimalKeeper.class);
System.out.println(animalKeeper.getAnimal().type());
context.close();
}

}

Output

Exception in thread “main” org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘animalKeeper’: Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.spring.example.bean.Animal] is defined: expected single matching bean but found 2: lion,tiger

Using the below annotations will also give the above error.

@Inject
private Animal animal;

@Autowired
private Animal animal;

All the annotations are doing the same thing that is trying to inject the dependency by Type.Type is Animal but it has 2 implementations (Tiger and Lion). Hence stuck with ambiguity exception.

Scenario 2 : Inject using field type as concrete class:- Using @Resource or @Inject or @Autowired

package com.spring.example.bean;

import javax.annotation.Resource;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;

import com.spring.example.config.BeanConfiguration;

@Component
public class AnimalKeeper {

@Resource
private Tiger animal;
//
// @Inject
// private Tiger animal;
//
// @Autowired
// private Tiger animal;

public Tiger getAnimal() {
return animal;
}

public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(BeanConfiguration.class);
AnimalKeeper animalKeeper = context.getBean(AnimalKeeper.class);
System.out.println(animalKeeper.getAnimal().type());
context.close();
}

}

Output: Tiger

All the annotations get successful injection.

Reason – All are trying to inject by type and type of the Animal is concrete class Tiger hence no ambiguity for injecting.

Scenario 3 : Injecting using field name:- Using @Resource or @Inject or @Autowired

package com.spring.example.bean;

import javax.annotation.Resource;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;

import com.spring.example.config.BeanConfiguration;

@Component
public class AnimalKeeper {

@Resource
private Animal tiger;
//
// @Inject
// private Animal tiger;
//
// @Autowired
// private Animal tiger;

public Animal getAnimal() {
return tiger;
}

public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(BeanConfiguration.class);
AnimalKeeper animalKeeper = context.getBean(AnimalKeeper.class);
System.out.println(animalKeeper.getAnimal().type());
context.close();
}

}

Output: Tiger

All the annotations will inject successfully.

Reason : It’s injecting by name , whenever we use @Component on the class, automatically class name itself is registered as a spring bean.

Tiger class register as tiger with container and tiger bean is only one available inside container so no ambiguity.

Scenario 4 : Using Qualifier with correct qualifier name:- Using @Resource or @Inject or @Autowired

package com.spring.example.bean;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;

import com.spring.example.config.BeanConfiguration;

@Component
public class AnimalKeeper {

@Resource
@Qualifier(“tiger”)
private Animal animal;

// @Inject
// @Qualifier(“tiger”)
// private Animal animal;
//
// @Autowired
// @Qualifier(“tiger”)
// private Animal animal;

public Animal getAnimal() {
return animal;
}

public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(BeanConfiguration.class);
AnimalKeeper animalKeeper = context.getBean(AnimalKeeper.class);
System.out.println(animalKeeper.getAnimal().type());
context.close();
}

}

Output:Tiger

All the annotation injects the dependent bean successfully.

Reason : All are injecting by using qualifier name which is tiger and we have only one bean with this name in the container.

Scenario 5 : Using Qualifier with incorrect qualifier name , but with correct field name

Here the behaviour of @Resource will be different from @Inject and @Autowired

Using @Resource – here Match by Name takes higher precedence.

package com.spring.example.bean;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;

import com.spring.example.config.BeanConfiguration;

@Component
public class AnimalKeeper {

@Resource
@Qualifier(“incorrect”)
private Animal tiger;

public Animal getAnimal() {
return tiger;
}

public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(BeanConfiguration.class);
AnimalKeeper animalKeeper = context.getBean(AnimalKeeper.class);
System.out.println(animalKeeper.getAnimal().type());
context.close();
}

}

Output:Tiger

Using @Inject or @Autowired:Qualifier has higher precedence over field name.

package com.spring.example.bean;

import javax.inject.Inject;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;

import com.spring.example.config.BeanConfiguration;

@Component
public class AnimalKeeper {

@Inject
@Qualifier(“incorrect”)
private Animal tiger;

// @Autowired
// @Qualifier(“incorrect”)
// private Animal tiger;

public Animal getAnimal() {
return tiger;
}

public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(BeanConfiguration.class);
AnimalKeeper animalKeeper = context.getBean(AnimalKeeper.class);
System.out.println(animalKeeper.getAnimal().type());
context.close();
}

}

Output
Exception in thread “main” org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name ‘animalKeeper’: Unsatisfied dependency expressed through field ‘tiger’: No qualifying bean of type [com.spring.example.bean.Animal] found for dependency [com.spring.example.bean.Animal]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject(), @org.springframework.beans.factory.annotation.Qualifier(value=incorrect)}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.spring.example.bean.Animal] found for dependency [com.spring.example.bean.Animal]: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@javax.inject.Inject(), @org.springframework.beans.factory.annotation.Qualifier(value=incorrect)}

Note: @Resource works fine and inject the Tiger type using the field name. But, @Autowired and @Inject throws exception as the Qualifier has higher precedence over field name.

Related Articles

2 comments

Leave a Reply

Your email address will not be published. Required fields are marked *