@Resource vs @Autowired


380

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

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

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


仅供参考-我删除了“更新”,应该将其作为一个单独的问题进行询问。根据此被拒绝的评论,“此编辑偏离了帖子的初衷。即使必须进行重大更改的编辑也应努力维护帖子所有者的目标”
mlo55 2015年

Answers:


194

在3.0之前的春季中,哪一个都不重要。

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

@Qualifier
@Retention(RUNTIME)
public @interface YourQualifier {}

所以你可以有

<bean class="com.pkg.SomeBean">
   <qualifier type="YourQualifier"/>
</bean>

要么

@YourQualifier
@Component
public class SomeBean implements Foo { .. }

然后:

@Inject @YourQualifier private Foo foo;

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


至于原始问题:两者都未指定注释的任何属性,而是按类型执行注入。区别在于:

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

这可能看起来像一个愚蠢的问题,但是当您使用这种注入方式时,是否需要使用public setter fooSomeBean带有Fooparam 的构造函数?
Snekse 2011年

@Snekse -得到了我的答案是:stackoverflow.com/questions/3536674/...
Snekse

不。您不需要任何。只是领域。(春天通过反射填充)
Bozho 2011年

@Bozho这个答案其实并不示区别@Resource@Autowired实际的答案是一个张贴@Ichthyo,我觉得这一个必须被更新。
鲍里斯·特鲁霍夫

1
是。实际上,有时我会通过提供一种更好的方法来回答问题。但是为了完整
起见

508

@Autowired(或@Inject)和两者均@Resource能很好地工作。但是在概念上或意义上存在差异

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

因此,基本上,这是两个截然不同的概念。不幸的是,的Spring-Implementation @Resource具有内置的后备功能,当解析名称失败时,该后备功能会加入。在这种情况下,它会@Autowired按类型退回到-kind resolution。虽然这种后备方式很方便,但是恕我直言,它引起了很多混乱,因为人们没有意识到概念上的差异,并且倾向于将其@Resource用于基于类型的自动装配。


81
是的,这是应该接受的答案。例如,如果您有带@Resource注释的字段,并且字段名称与容器中的bean的ID匹配,则Spring org.springframework.beans.factory.BeanNotOfRequiredTypeException如果它们的类型不同,则会抛出 该异常-这是因为bean首先在@Resource注释中按名称而不是按类型进行匹配。但是,如果该属性的名称与Bean的名称不匹配,那么Spring将按类型将它们连接起来。
鲍里斯·特鲁霍夫

当您尝试使用简单的MAP时,您可以参考另一篇文章,介绍这两者之间的区别。stackoverflow.com/questions/13913752/...
Anver Sadhat

4
+1用于实际回答问题,而不是像接受的答案那样简单地推荐完全不同的“最佳实践”。我还发现此博客文章对所有三种注释样式的几种常见场景的结果都很有帮助:blogs.sourceallies.com/2011/08/…–
Jules

1
对于读者而言,请在此处找到@Jules指向的文章摘要:stackoverflow.com/a/23887596/363573
Stephan

3
这就意味着一个含义:当您想要注入一个Map / List bean时,@Autowire它既不会也不会工作。@Resource在这种情况下,您将不得不使用。
里卡多·范·登·布鲁克

76

主要区别是@Autowired弹簧注释。而@Resource由JSR-250指定的,正如你所指出自己。因此,后者是Java的一部分,而前者是特定于Spring的。

因此,从某种意义上说,您的建议是正确的。我发现人们可以使用它@Autowired@Qualifier因为它更强大。从某个框架过渡到另一个框架被认为是不可能的,即使不是神话,尤其是在Spring的情况下。


7
+1,因为@Autowired@Qualifier真正威力比JSR标准@Resource注释(可选认为依赖例如用@Autowired(required=false),你不能做到这一点与@Resource
斯特凡Haberl

70

我想强调从一个评论@Jules这个回答这个问题。该评论带来了一个有用的链接:带有@ Resource,@ Autowired和@Inject的Spring Injection。我鼓励您完整阅读它,但是这里简要概述了它的有用性:

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

@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注入


39

这是我从Spring 3.0.x参考手册中获得的

小费

如果您打算通过名称表示注释驱动的注入,则即使技术上可以通过@Qualifier值引用bean名称,也不要主要使用@Autowired。而是使用JSR-250 @Resource批注,该批注的语义定义是通过其唯一名称标识特定的目标组件,而声明的类型与匹配过程无关。

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

@Autowired适用于字段,构造函数和多参数方法,从而允许在参数级别缩小限定符注释的范围。相比之下,只有具有单个参数的字段和bean属性设置器方法才支持@Resource。因此,如果您的注入目标是构造函数或多参数方法,请坚持使用限定符。


对于当前版本,请参阅docs.spring.io/spring/docs/current/spring-framework-reference/…(技巧已更新)
Lu55,18年

27

@Autowired + @Qualifier仅适用于Spring DI,如果您以后想使用其他DI,则@Resource是一个不错的选择。

我发现非常重要的另一个区别是@Qualifier不支持动态bean接线,因为@Qualifier不支持占位符,而@Resource则很好。

例如:如果您的接口具有多个这样的实现

interface parent {

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

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

}

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

@Autowired
@Qualifier("actualService") or 
@Qualifier("stubbedService") 
Parent object;

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

@Resource(name="${service.name}")
Parent object;  

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

#service.name=actualService
 service.name=stubbedService

希望能帮助到某人:)


16

他们两个都一样好。使用Resource的优势在于将来如果您希望使用除Spring之外的其他DI框架,则代码更改将更加简单。使用自动装配,您的代码与弹簧DI紧密结合。


17
永远不会发生。即使这样做-对注释名称进行查找/替换也将是您最少的问题。
Daniel Alexiuc 2015年

13

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

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

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

@Autowired / @Inject

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

@Resource

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


6

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

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


2

@Resource通常由通过JNDI定义的高级对象使用。@Autowired@Inject将由更常见的豆使用。

据我所知,它不是规范,也不是约定。这是标准代码使用这些批注的逻辑方式。


0

作为此处的注释: SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext并且SpringBeanAutowiringSupport.processInjectionBasedOnServletContext 不适用于@Resource 注释。因此,有区别。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.