0% found this document useful (0 votes)
94 views

Annotations Annotation Package Source: Spring Tool Suite

The document compares the @Resource, @Autowired, and @Inject annotations in Spring for injecting dependencies between beans. Through a series of tests, it finds that @Autowired and @Inject behave identically by first matching by type, then qualifiers, then name. @Resource first matches by name, then type, then qualifiers. While @Resource may be slightly faster, the differences are negligible. The document recommends explicitly naming components, using @Resource with the name attribute, only using @Qualifier for lists of similar beans, and scanning specific packages to reduce unnecessary beans in the context.

Uploaded by

murthy_oct24
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
94 views

Annotations Annotation Package Source: Spring Tool Suite

The document compares the @Resource, @Autowired, and @Inject annotations in Spring for injecting dependencies between beans. Through a series of tests, it finds that @Autowired and @Inject behave identically by first matching by type, then qualifiers, then name. @Resource first matches by name, then type, then qualifiers. While @Resource may be slightly faster, the differences are negligible. The document recommends explicitly naming components, using @Resource with the name attribute, only using @Qualifier for lists of similar beans, and scanning specific packages to reduce unnecessary beans in the context.

Uploaded by

murthy_oct24
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 5

Overview

Ive 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 didnt feel like I had a complete picture.
Annotations
Annotation
@Resource
@Inject
@Qualifier
@Autowired

Package
Source
javax.annotation
Java
javax.inject
Java
javax.inject
Java
org.springframework.bean.factory Spring

In order to explore the behavior of each annotation I fired up Spring Tool Suite and started debugging the
code. I used Spring 3.0.5.RELEASE in my research. The following is a summary of my findings.

The Code
I wanted to know how @Resource, @Autowired, and @Inject resolved dependencies. I 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 {

I setup a Spring context that scans both of these packages for beans marked with @Component.
<context:component-scan base-package="com.sourceallies.organization"/>
<context:component-scan base-package="com.sourceallies.person"/>

Tests
Test 1: Ambiguous Beans

In this test I injected a Party bean that has multiple implementations in the Spring context.
@Resource
private Party party;
@Autowired
private Party party;
@Inject
private Party party;

In all three cases a NoSuchBeanDefinitionException is thrown. While this exceptions 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;

@Resource can also take an optional name attribute. This is equivalent to the @Resource code above. In
this case the field variable name remains party. There is no equivalent syntax for @Autowired or
@Inject. Instead you would have to use a @Qualifier. This syntax will be covered later.
@Resource(name="person")
private Party party;

All four of these styles inject the Person bean.

Test 3: Field Type


In this test I changed the type to be a Person.
@Resource
private Person party;
@Autowired
private Person party;
@Inject
private Person party;

All of these annotations inject the Person bean.

Test 4: Default Name Qualifier


In this test I use a @Qualifier annotation to point to the default name of the Person component.
@Resource
@Qualifier("person")
private Party party;

@Autowired
@Qualifier("person")
private Party party;
@Inject
@Qualifier("person")
private Party party;

All of these annotations inject the Person bean.

Test 5: Qualified Name


I added a @Qualifier annotation to the Person class
package com.sourceallies.person;
...
@Component
@Qualifier("personBean")
public class Person implements Party {

In this test I use a @Qualifier annotation to point to the qualified name of the Person component.
@Resource
@Qualifier("personBean")
private Party party;
@Autowired
@Qualifier("personBean")
private Party party;
@Inject
@Qualifier("personBean")
private Party party;

All of these annotations inject the Person bean.

Test 6: List of Beans


In this test I inject a list of beans.
@Resource
private List<Party> parties;
@Autowired
private List<Party> parties;
@Inject
private List<Party> parties;

All of these annotations inject 2 beans into the list. This can also be accomplished with a
@Qualifier. Each bean marked with a specific qualifier will be added to the list.

Test 7: Conflicting messages


In this test I add a bad @Qualifier 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.
org.springframework.beans.factory.NoSuchBeanDefinitionException:
No matching bean of type [com.sourceallies.Party] found for dependency:
expected at least 1 bean which qualifies as autowire candidate for this dependency.
Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true),
@org.springframework.beans.factory.annotation.Qualifier(value=bad)}

Conclusions
With the exception of test 2 & 7 the configuration and outcomes were identical. When I looked under the
hood I determined that the @Autowired and @Inject annotation behave identically. Both of these
annotations use the AutowiredAnnotationBeanPostProcessor to inject dependencies. @Autowired and
@Inject can be used interchangeable to inject Spring beans. However the @Resource annotation uses the
CommonAnnotationBeanPostProcessor to inject dependencies. Even though they use different post
processor classes they all behave nearly identically. Below is a summary of their execution paths.
@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)
While it could be argued that @Resource will perform faster by name than @Autowired and @Inject it
would be negligible. This isnt a sufficient reason to favor one syntax over the others. I do however favor
the @Resource annotation for its concise notation style.
@Resource(name="person")
@Autowired
@Qualifier("person")
@Inject
@Qualifier("person")

You may argue that they can be equal concise if you use the field name to identify the bean name.
@Resource
private Party person;
@Autowired
private Party person;
@Inject
private Party person;

True enough, but what happens if you want to refactor your code? By simply renaming the field name
youre no longer referring to the same bean. I recommend the following practices when wiring beans with
annotations.
Spring Annotation Style Best Practices

1. Explicitly name your component [@Component(beanName)]


2. Use @Resource with the name attribute [@Resource(name=beanName)]
3. Avoid @Qualifier annotations unless you want to create a list of similar beans. For example you may
want to mark a set of rules with a specific @Qualifier annotation. This approach makes it simple to
inject a group of rule classes into a list that can be used for processing data.
4. Scan specific packages for components [context:component-scan basepackage=com.sourceallies.person]. While this will result in more component-scan configurations it
reduces the chance that youll add unnecessary components to your Spring context.

You might also like