@Autowired, @Resource and @Inject
Let us understand @Autowired,@Resource and @Inject
All these annotations are used to inject dependent objects in spring.
Lets see what is their differences
@Resource -> javax.annotation
@Inject -> javax.inject
@Autowired -> org.springframework.beans.factory.annotation
Let’s start with the below example
Create Vehicle.java
- package com.kb.autowire_resource_inject;
- public interface Vehicle {
- }
package com.kb.autowire_resource_inject; public interface Vehicle { }
Create TwoWheeler.java
- package com.kb.autowire_resource_inject;
- import org.springframework.stereotype.Component;
- @Component
- public class TwoWheeler implements Vehicle {
- }
package com.kb.autowire_resource_inject; import org.springframework.stereotype.Component; @Component public class TwoWheeler implements Vehicle { }
Create FourWheeler.java
- package com.kb.autowire_resource_inject;
- import org.springframework.stereotype.Component;
- @Component
- public class FourWheeler implements Vehicle {
- }
package com.kb.autowire_resource_inject; import org.springframework.stereotype.Component; @Component public class FourWheeler implements Vehicle { }
Let’s see some scenarios to understand it clearly
Scenario 1 -> Inject using Interface type
- @Resource
- Vehicle vehicle;
- @Autowired
- Vehicle vehicle;
- @Inject
- Vehicle vehicle;
@Resource Vehicle vehicle; @Autowired Vehicle vehicle; @Inject Vehicle vehicle;
All the above annotations are doing the same thing that is trying to inject the dependent object by Type.
Type is Vehicle but it has 2 implementations (TwoWheeler and FourWheeler)
Hence stuck with ambiguity exception as below
Scenario 2 -> Inject using field type as concrete class
- @Resource
- TwoWheeler vehicle;
- @Autowired
- TwoWheeler vehicle;
- @Inject
- TwoWheeler vehicle;
@Resource TwoWheeler vehicle; @Autowired TwoWheeler vehicle; @Inject TwoWheeler vehicle;
Now all the above annotations get successful injection of dependent objects.
Reason – All are trying to inject by type and type of the vehicle is concrete class TwoWheeler hence no ambiguity for injecting.
Scenario 3 -> injecting using field name
- @Resource
- Vehicle twoWheeler;
- @Autowired
- Vehicle twoWheeler;
- @Inject
- Vehicle twoWheeler;
@Resource Vehicle twoWheeler; @Autowired Vehicle twoWheeler; @Inject Vehicle twoWheeler;
Now all the above annotations will inject the dependent object successfully.
Reason : It’s injecting by name , whenever we use @Component on the class, automatically class name itself is registered as a spring bean.
TwoWheeler class register as twoWheeler with container and twoWheeler bean is only one available inside container so no ambiguity.
Scenario 4 -> Qualifier with default bean name
- @Resource
- @Qualifier("twoWheeler")
- private Vehicle vehicle;
- @Autowired
- @Qualifier("twoWheeler")
- private Vehicle vehicle;
- @Inject
- @Qualifier("twoWheeler")
- private Vehicle vehicle;
@Resource @Qualifier("twoWheeler") private Vehicle vehicle; @Autowired @Qualifier("twoWheeler") private Vehicle vehicle; @Inject @Qualifier("twoWheeler") private Vehicle vehicle;
All the above annotation injects the dependent bean successfully.
Reason : All are injecting by using qualifier name which is thoWheeler and we have only one bean with this name in the container.
Scenario 5 -> Injecting list of beans
- @Resource
- private List<Vehicle> vehicles;
- @Autowired
- private List<Vehicle> vehicles;
- @Inject
- private List<Vehicle> vehicles;
@Resource private List<Vehicle> vehicles; @Autowired private List<Vehicle> vehicles; @Inject private List<Vehicle> vehicles;
all the above annotations injects the dependencies to the List of supertype class Vehicle.
Scenario 6 -> special behavior of @Resource during beans conflict while injecting
- @Resource
- @Qualifier("noSuchBean")
- private Vehicle twoWheeler;
- @Autowired
- @Qualifier("noSuchBean")
- private Vehicle twoWheeler;
- @Inject
- @Qualifier("noSuchBean")
- private Vehicle twoWheeler;
@Resource @Qualifier("noSuchBean") private Vehicle twoWheeler; @Autowired @Qualifier("noSuchBean") private Vehicle twoWheeler; @Inject @Qualifier("noSuchBean") private Vehicle twoWheeler;
In above scenario twoWheeler is not injected using @Autowired and @Inject
But twoWheeler is injected using @Resource.
Reason -> @Resource uses the variable name which is twoWheeler to make dependency injection and ignores the @Qualifier.
But @Autowired and @Inject fails as they try to find a bean name specified in @Qualifier.
So @Autowired and @Inject works very similar but @Resource has bit different feature.
The order of choosing injection type
@Autowired and @Inject
1.Match by Type -> bean with same Data type of the variable should be available in spring container
2.Restricts by Qualifier -> If bean of variable’s data type not found or many implementation of the type available then it looks for any qualifier defined and if defined it uses Qualifier and wont go for 3rd option
3.Matches by Name –> searches the bean in the spring whose id should be same as variable name defined while autowiring.
@Resource
1.Match by Name -> first it searches for the bean in spring whose id should be same as variable name declared.
2.Match by Type -> bean with same Data type of the variable should be available in spring container
3.Restricts by Qualifier(ignores if 1st attempt said above by name matches)
awesome
Great work..
Thank you !!
Superb explanation