Spring Injection with @Resource, @Autowired and @Inject
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; |
‘Organization’ is a component and it implements ‘Party’.
package com.sourceallies.organization; |
I setup a Spring context that scans both of these packages for beans marked with ‘@Component’.
<context:component-scan base-package="com.sourceallies.organization"/> |
Tests
Test 1: Ambiguous Beans
In this test I injected a ‘Party’ bean that has multiple implementations in the Spring context.
@Resource |
@Autowired |
@Inject |
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: |
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 |
@Autowired |
@Inject |
‘@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") |
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 |
@Autowired |
@Inject |
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 |
@Autowired |
@Inject |
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; |
In this test I use a ‘@Qualifier’ annotation to point to the qualified name of the ‘Person’ component.
@Resource |
@Autowired |
@Inject |
All of these annotations inject the ‘Person’ bean.
Test 6: List of Beans
In this test I inject a list of beans.
@Resource |
@Autowired |
@Inject |
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 |
@Autowired |
@Inject |
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: |
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
- Matches by Type
- Restricts by Qualifiers
- Matches by Name
@Resource
- Matches by Name
- Matches by Type
- 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 |
@Inject |
You may argue that they can be equal concise if you use the field name to identify the bean name.
@Resource |
@Autowired |
@Inject |
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
- Explicitly name your component [@Component("beanName")]
- Use ‘@Resource’ with the ‘name’ attribute [@Resource(name="beanName")]
- 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.
- 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的更多相关文章
- spring下应用@Resource, @Autowired 和 @Inject注解进行依赖注入的差异
为了探寻 '@Resource', '@Autowired', 和'@Inject'如何解决依赖注入中的问题,我创建了一个"Party"接口,和它的两个实现类"Perso ...
- Spring 注释标签@Resource @Autowired 和@Inject的区别
一些spring的开发人员在使用这三个标签进行注入的时候感到困惑.我来尝试解释一下这三个注解的主要区别.事实上,这三者非常相似,只存在一些微小的差别.在稍后的文章中会进行解释. @Resource-在 ...
- Spring @Resource, @Autowired and @Inject 注入
Overview I’ve been asked several times to explain the difference between injecting Spring beans with ...
- Spring依赖注入:@Autowired,@Resource和@Inject区别与实现原理
一.spring依赖注入使用方式 @Autowired是spring框架提供的实现依赖注入的注解,主要支持在set方法,field,构造函数中完成bean注入,注入方式为通过类型查找bean,即byT ...
- annotation之@Autowired、@Inject、@Resource三者区别
一.@Autowired 1.@Autowired是spring自带的注解,通过‘AutowiredAnnotationBeanPostProcessor’ 类实现的依赖注入: 2.@Autowire ...
- SpringBoot入门教程(十六)@Autowired、@Inject、@Resource
@Resource,@Autowired,@Inject 这3种都是用来注入bean的,它们属于不同的程序中.详情参见下表: v区别 ANNOTATION PACKAGE SOURCE 作用域 实现方 ...
- 死磕Spring之IoC篇 - @Autowired 等注解的实现原理
该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址 进行阅读 Spring 版本:5.1. ...
- 【解决方案】 org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userHandler': Injection of resource dependencies failed;
一个错误会浪费好多青春绳命 鉴于此,为了不让大家也走弯路,分享解决方案. [错误代码提示] StandardWrapper.Throwableorg.springframework.beans.fac ...
- Spring JTA multiple resource transactions in Tomcat with Atomikos example
http://www.byteslounge.com/tutorials/spring-jta-multiple-resource-transactions-in-tomcat-with-atomik ...
随机推荐
- 【BZOJ】【1019】【SHOI2008】汉诺塔
递推/DP 类似普通汉诺塔的一个递推(模拟?$10^{18}$没法模拟吧…… 题解:http://blog.csdn.net/regina8023/article/details/43016813 因 ...
- .NET设计模式(3):抽象工厂模式(Abstract Factory)(转)
概述 在软件系统中,经常面临着“一系列相互依赖的对象”的创建工作:同时由于需求的变化,往往存在着更多系列对象的创建工作.如何应对这种变化?如何绕过常规的对象的创建方法(new),提供一种“封装机制”来 ...
- ASP.NET中的事件处理
一.ASP.NET中的事件主要支持3个主要的事件组:1.包含在asp.net生成页面时自动生成,我们使用这些事件建立页面(如page_load等)2.包含了用户与页面交互时发生的所有事件(这种最强大) ...
- geotools解析SLD中的elsefilter为什么里面的filter无效
原因是在org.geotools.renderer.lite.StreamingRenderer中的process函数: /** * @param rf * @param feature * @par ...
- Android App集成支付宝
原地址:http://blog.csdn.net/wenbingoon/article/details/7933078 手机的在线支付,被认为是2012年最看好的功能,我个人认为这也是移动互联网较传统 ...
- leetcode course shedule
题目就不说了,问题本质就是在一个有向图中查找它是不是存在环. 上网百度了一下,方法是,找出图中入度为0 的点,将以它为起点的边去掉. 重复这一动作,直到所有的边都被去掉(没有环)或者存在边但是无法再去 ...
- 总结 | 如何测试你自己的 RubyGem
如何测试一个Gem gem 开发完了,想要给别人用,那就需要测试啊,测试一个 gem 其实很简单,这里我们用 minitest 为例, rspec 也一样适用.先来看看我们当前这个 gem 的目录结构 ...
- FZU2165 v11(带权的重复覆盖)
题意:有n个boss,m种武器,每种武器选用的时候需要有一定的花费ci,然后这个武器可以消灭掉其中一些BOSS,问你消灭完所有的BOSS,需要的最少花费是多少. 当时比赛的时候,看到这题以为是什么网络 ...
- Linux信号处理1
函数原型 NAME signal - ANSI C signal handling SYNOPSIS #include <signal.h> typedef void (*sighandl ...
- BZOJ 1015: [JSOI2008]星球大战starwar 并查集
1015: [JSOI2008]星球大战starwar Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝 ...