August 1st, 2011 by David Kessler

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.

Annotations

Annotation Package Source
@Resource javax.annotation Java
@Inject javax.inject Java
@Qualifier javax.inject Java
@Autowired 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 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;

‘@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 isn’t a sufficient reason to favor one syntax over the others. I do however favor the ‘@Resource’ annotation for it’s 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 you’re 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 base-package="com.sourceallies.person"]. While this will result in more component-scan configurations it reduces the chance that you’ll add unnecessary components to your Spring context.

Following these guidelines will increase the readability and stability of your Spring annotation configurations.

- See more at: http://blogs.sourceallies.com/2011/08/spring-injection-with-resource-and-autowired/#sthash.9f0qN5FD.dpuf

Spring Injection with @Resource, @Autowired and @Inject的更多相关文章

  1. spring下应用@Resource, @Autowired 和 @Inject注解进行依赖注入的差异

    为了探寻 '@Resource', '@Autowired', 和'@Inject'如何解决依赖注入中的问题,我创建了一个"Party"接口,和它的两个实现类"Perso ...

  2. Spring 注释标签@Resource @Autowired 和@Inject的区别

    一些spring的开发人员在使用这三个标签进行注入的时候感到困惑.我来尝试解释一下这三个注解的主要区别.事实上,这三者非常相似,只存在一些微小的差别.在稍后的文章中会进行解释. @Resource-在 ...

  3. Spring @Resource, @Autowired and @Inject 注入

    Overview I’ve been asked several times to explain the difference between injecting Spring beans with ...

  4. Spring依赖注入:@Autowired,@Resource和@Inject区别与实现原理

    一.spring依赖注入使用方式 @Autowired是spring框架提供的实现依赖注入的注解,主要支持在set方法,field,构造函数中完成bean注入,注入方式为通过类型查找bean,即byT ...

  5. annotation之@Autowired、@Inject、@Resource三者区别

    一.@Autowired 1.@Autowired是spring自带的注解,通过‘AutowiredAnnotationBeanPostProcessor’ 类实现的依赖注入: 2.@Autowire ...

  6. SpringBoot入门教程(十六)@Autowired、@Inject、@Resource

    @Resource,@Autowired,@Inject 这3种都是用来注入bean的,它们属于不同的程序中.详情参见下表: v区别 ANNOTATION PACKAGE SOURCE 作用域 实现方 ...

  7. 死磕Spring之IoC篇 - @Autowired 等注解的实现原理

    该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读 Spring 版本:5.1. ...

  8. 【解决方案】 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userHandler': Injection of resource dependencies failed;

    一个错误会浪费好多青春绳命 鉴于此,为了不让大家也走弯路,分享解决方案. [错误代码提示] StandardWrapper.Throwableorg.springframework.beans.fac ...

  9. Spring JTA multiple resource transactions in Tomcat with Atomikos example

    http://www.byteslounge.com/tutorials/spring-jta-multiple-resource-transactions-in-tomcat-with-atomik ...

随机推荐

  1. Codeforces Round #350 (Div. 2) E. Correct Bracket Sequence Editor 模拟

    题目链接: http://codeforces.com/contest/670/problem/E 题解: 用STL的list和stack模拟的,没想到跑的还挺快. 代码: #include<i ...

  2. 【BZOJ】【3550】【ONTAK2010】Vacation

    网络流/费用流 Orz太神犇了这题…… 我一开始想成跟Intervals那题一样了……每个数a[i]相当于覆盖了(a[i]-n,a[i]+n)这个区间……但是这样是错的!!随便就找出反例了……我居然还 ...

  3. SimpleDateFormat

    范例: Date date = new Date();SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MMM-dd,E,HH. ...

  4. Segment Tree 分类: ACM TYPE 2014-08-29 13:04 97人阅读 评论(0) 收藏

    #include<iostream> #include<cstdio> using namespace std; struct node { int l, r, m; int ...

  5. Post 的数据被截断

    原因: Form 域 POST 提交数据 100K(可能不是这个值) 限制的解决方案   因为微软这个限制是对表单内每个域(第一个控件)的限制.问题的解决办法是,对于一个需要发送大数据的域,在提交表单 ...

  6. 关于面向对象--oop

    这两天在做大数据方面的项目看到关于job作业调度的设计,扣了两天了,感触良多,记下来做个反省. 这是一个精简版的图,其中还有一些没有划到,其实到这里目前对我来说已经足够了. 看完图之后进行分析,我只抛 ...

  7. cache应用(asp.net 2.0 SQL数据缓存依赖 [SqlCacheDependency ] )

    Asp.net 2.0 提供了一个新的数据缓存功能,就是利用sql server2005 的异步通知功能来实现缓存 1.首先在sqlserver2005 中创建一个test的数据库. 在SQL Ser ...

  8. javascript实现数据结构:串--堆分配存储表示

    堆分配存储表示 这种存储表示的特点是,仍以一组地址连续的存储单元存放串值字符序列,但它们的存储空间是在程序执行过程中动态分配而得. 结构图: 实现: function HString(){ this. ...

  9. nginx js、css多个请求合并为一个请求(concat模块)

    模块介绍 mod_concat模块由淘宝开发,目前已经包含在tengine中,并且淘宝已经在使用这个nginx模块.不过塔暂时没有包含在nginx中.这个模块类似于apache中的modconcat. ...

  10. visual studio 2012 Github

    前言 一直以来都想使用Git来管理自己平时积累的小代码,就是除了工作之外的代码了.有时候自己搞个小代码,在公司写了,就要通过U盘或者网盘等等一系列工具进行Copy,然后回家才能继续在原来的基础上作业. ...