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โ.
