@Resource vs @Autowired

mlo*_*o55 359 java spring annotations dependency-injection autowired

我应该在DI中使用哪个注释@Resource(jsr250)或@Autowired(特定于Spring)?

我已经成功地在过去使用两种,@Resource(name="blah")@Autowired @Qualifier("blah")

我的直觉是坚持使用@Resource标签,因为它已被jsr人批准.
有人对此有强烈的想法吗?

Ich*_*hyo 487

两者@Autowired(或@Inject)@Resource都同样有效.但是意义上存在概念差异或差异

  • @Resource意味着按名称给我一个已知的资源.该名称是从带注释的setter或字段的名称中提取的,或者是从name-Parameter中获取的.
  • @Inject@Autowired尝试按类型连接合适的其他组件.

所以,基本上这些是两个截然不同的概念.不幸的是,Spring-Implementation @Resource有一个内置的回退功能,当分辨率按名称失败时,它会启动.在这种情况下,它会回@Autowired退到类型的-kind分辨率.虽然这种后备很方便,但恕我直言会引起很多混乱,因为人们不知道概念上的差异,并倾向于使用@Resource基于类型的自动装配.

  • 是的,这应该是一个可接受的答案.例如,如果你有一个`@ Resource`注释字段,并且字段名称与容器中bean的id匹配,那么如果它们的类型不同,Spring将抛出`org.springframework.beans.factory.BeanNotOfRequiredTypeException` - 这是因为bean是第一个在`@ Resource`注释中按名称匹配,而不是按类型匹配.但是如果属性的名称与bean的名称不匹配,那么Spring将按类型连接它们. (77认同)
  • +1实际回答问题,而不是简单地推荐一个完全不同的"最佳实践"作为接受的答案.我还发现了这篇博文,其中显示了所有三种注释样式的几种常见场景的结果,有用:http://blogs.sourceallies.com/2011/08/spring-injection-with-resource-and-autowired/ (4认同)
  • 其中一个含义是:当你想要注入一个Map/List bean时,`@Autowire`不能也不会工作.在这种情况下,你将不得不使用`@ Resource`. (3认同)

Boz*_*zho 187

在3.0之前的春季,哪一个并不重要.

在3.0版本中,支持标准(JSR-330)注释@javax.inject.Inject- 使用它,结合使用@Qualifier.请注意,spring现在也支持@javax.inject.Qualifier元注释:

@Qualifier
@Retention(RUNTIME)
public @interface YourQualifier {}
Run Code Online (Sandbox Code Playgroud)

所以你可以拥有

<bean class="com.pkg.SomeBean">
   <qualifier type="YourQualifier"/>
</bean>
Run Code Online (Sandbox Code Playgroud)

要么

@YourQualifier
@Component
public class SomeBean implements Foo { .. }
Run Code Online (Sandbox Code Playgroud)

然后:

@Inject @YourQualifier private Foo foo;
Run Code Online (Sandbox Code Playgroud)

这减少了字符串名称的使用,这可能拼写错误并且难以维护.


至于原始问题:两者都没有指定注释的任何属性,而是按类型执行注入.不同之处是:

  • @Resource 允许您指定注入的bean的名称
  • @Autowired 允许您将其标记为非强制性.

  • 为Spring 3新功能+1.我希望你不介意我对这篇文章的更正. (2认同)
  • @Bozho这个答案实际上没有显示`@Resource`和`@Autowired`之​​间的区别,实际答案是@Ichthyo发布的,我认为这个必须更新。 (2认同)

Ade*_*ari 73

主要区别在于@Autowired弹簧注释.然而@Resource,正如您自己指出的那样,由JSR-250指定.所以后者是Java的一部分,而前者是Spring特有的.

因此,从某种意义上说,你是正确的.我发现人们使用@Autowired@Qualifier因为它更强大.如果不是神话,那么从一些框架转移到其他框架被认为是不太可能的,特别是在Spring的情况下.

  • +1,因为`@Autowired`和`@Qualifier`真的比JSR标准`@Source`注释更强大(想想可选的依赖关系,例如`@Autowired(required = false)`.你做不到与`@资源') (6认同)

Ste*_*han 64

我想强调@Jules关于这个问题的答案的一个评论.该注释带来了一个有用的链接:Spring注入@Resource,@ Autowired和@Inject.我鼓励你完全阅读它,但是这里有一个快速的摘要:

注释如何选择正确的实现?

@Autowired@Inject

  1. 按类型匹配
  2. 按资格限制
  3. 按名称匹配

@Resource

  1. 按名称匹配
  2. 按类型匹配
  3. 按限定符限制(如果按名称找到匹配则忽略)

我应该使用哪些注释(或组合)注入我的bean?

  1. 明确命名组件[@Component("beanName")]

  2. 使用@Resourcename属性[@Resource(名称= "beanName")]

我为什么不用@Qualifier

@Qualifier除非您要创建类似bean的列表,否则请避免使用注释.例如,您可能希望使用特定@Qualifier注释标记一组规则.这种方法使得将一组规则类注入可用于处理数据的列表变得简单.

豆注射会减慢我的程序吗?

扫描组件的特定包[context:component-scan base-package="com.sourceallies.person"].虽然这会导致更多component-scan配置,但它会减少您向Spring上下文添加不必要组件的可能性.


参考: 使用@Resource,@ Autowired和@Inject进行Spring注入


小智 38

这是我从Spring 3.0.x参考手册中得到的: -

小费

如果您打算按名称表达注释驱动的注入,请不要主要使用@Autowired,即使技术上能够通过@Qualifier值引用bean名称.相反,使用JSR-250 @Resource注释,该注释在语义上定义为通过其唯一名称标识特定目标组件,声明的类型与匹配过程无关.

作为此语义差异的特定结果,无法通过@Autowired注入本身定义为集合或映射类型的bean,因为类型匹配不适用于它们.对这样的bean使用@Resource,通过唯一名称引用特定的集合或映射bean.

@Autowired适用于字段,构造函数和多参数方法,允许在参数级别缩小限定符注释.相比之下,@ Resource仅支持具有单个参数的字段和bean属性setter方法.因此,如果您的注射目标是构造函数或多参数方法,请坚持使用限定符.


Ali*_*Ali 21

@Autowired + @Qualifier只适用于spring DI,如果你想在将来使用其他DI,@ Resource是个不错的选择.

我发现非常重要的其他差异是@Qualifier不支持动态bean连接,因为@Qualifier不支持占位符,而@Resource非常好.

例如:如果您有一个具有多个此类实现的接口

interface parent {

}
@Service("actualService")
class ActualService implements parent{

}
@Service("stubbedService")
class SubbedService implements parent{

}
Run Code Online (Sandbox Code Playgroud)

使用@Autowired和@Qualifier,您需要设置特定的子实现

@Autowired
@Qualifier("actualService") or 
@Qualifier("stubbedService") 
Parent object;
Run Code Online (Sandbox Code Playgroud)

使用@Resource时不提供占位符,你可以放置占位符并使用属性文件注入特定的子实现

@Resource(name="${service.name}")
Parent object;  
Run Code Online (Sandbox Code Playgroud)

其中service.name在属性文件中设置为

#service.name=actualService
 service.name=stubbedService
Run Code Online (Sandbox Code Playgroud)

希望有人帮助:)


Tej*_*eni 16

两者都同样好.如果您想要除spring之外的其他DI框架,将来使用Resource的优势在于,您的代码更改将更加简单.使用Autowired,您的代码与弹簧DI紧密结合.

  • 永远不会发生.即使它确实如此 - 在注释名称上进行查找/替换将是您遇到的最少问题. (16认同)

Amo*_*gei 10

从这两个批注的基类进行批判性分析时,您将意识到以下差异。

@Autowired用于AutowiredAnnotationBeanPostProcessor 注入依赖项。
@Resource用于CommonAnnotationBeanPostProcessor注入依赖项。

即使它们使用不同的后处理器类,它们的行为也几乎相同。差异主要在于它们的执行路径,下面我将重点介绍它们。

@Autowired / @Inject
Run Code Online (Sandbox Code Playgroud)

1.按类型
匹配2.按预选赛
限制3.按名称匹配

@Resource
Run Code Online (Sandbox Code Playgroud)

1.按名称
匹配2.按类型
匹配3.按限定词限制(如果按名称找到匹配项则忽略)


Boh*_*nko 5

通过@Resource执行bean自注入,可能需要运行bean后处理器添加的所有额外逻辑,例如与事务或安全相关的东西。

使用Spring 4.3+ @Autowired也可以做到这一点。