Overview
I’ve been asked several times to explain the difference between injecting Spring beans with ‘@Resource’, ‘@Autowired’, and ‘@Inject’. While I received a few opinions from colleagues and read a couple of posts on this topic I didn’t feel like I had a complete picture.
ANNOTATION
|
PACKAGE
|
SOURCE
|
@Resource
|
javax.annotation
|
Java
|
@Inject
|
javax.inject
|
Java
|
@Qualifier
|
javax.inject
|
Java
|
@Autowired
|
org.springframework.bean.factory
|
Spring
|
I am using below code to check the difference in between @Resource @Autowired and @Inject annotations. I wanted to know how ‘@Resource’, ‘@Autowired’, and ‘@Inject’ resolved dependencies. I have created an interface called ‘Party’ and created two implementations classes. This allowed me to inject beans without using the concrete type. This provided the flexibility I needed to determine how Spring resolves beans when there are multiple type matches.
public interface Party { }
‘Person’ is a component and it implements ‘Party’.
package com.sourceallies.person; @Component public class Person implements Party { }
‘Organization’ is a component and it implements ‘Party’.
package com.sourceallies.organization; @Component public class Organization implements Party { }
Test Our Code
Test 1: Ambiguous Beans
In this test I injected a ‘Party’ bean that has multiple implementations in the Spring context and we will use DI in different classes to inject the Party Depenndacy.
@Resource private Party party;
@Autowired private Party party;
@Inject private Party party;
In all three cases a ‘NoSuchBeanDefinitionException’is thrown. While this exception’s name implies that no beans were found, the message explains that two beans were found. All of these annotations result in the same exception.
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No unique bean of type [com.sourceallies.Party] is defined: expected single matching bean but found 2:[organization, person]
Test 2: Field Name
In this test I named the Party field person. By default beans marked with ‘@Component’ will have the same name as the class. Therefore the name of the class ‘Person’ is person.
@Resource private Party person;
@Autowired private Party person;
@Inject private Party person;
Test 3: With Qualifier
In this test I add a bad ‘@Qualifier’(which is not available in our Spring context) and a matching field name.
@Resource @Qualifier("bad") private Party person;
@Autowired @Qualifier("bad") private Party person;
@Inject @Qualifier("bad") private Party person;
In this case the field marked with ‘@Resource’uses the field name and ignores the ‘@Qualifier’. As a result the ‘Person’ bean is injected.
However the ‘@Autowired’ and ‘@Inject’ field throw a ‘NoSuchBeanDefinitionException’ error because it can not find a bean that matches the ‘@Qualifier’.