@Resource vs @Autowired

时间:2010-11-04 02:50:59

标签: java spring dependency-injection annotations autowired

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

我过去成功使用了@Resource(name="blah")@Autowired @Qualifier("blah")

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

11 个答案:

答案 0 :(得分:460)

@Autowired(或@Inject)和@Resource同样有效。但是意义上存在概念差异或差异

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

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

答案 1 :(得分:173)

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

在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允许您将其标记为非强制性。

答案 2 :(得分:72)

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

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

答案 3 :(得分:63)

我想强调@Jules this answer对此问题的一条评论。评论带来了一个有用的链接:Spring Injection with @Resource, @Autowired and @Inject。我鼓励你完全阅读它,但是这里有一个快速的摘要:

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

@Autowired@Inject

  1. 按类型匹配
  2. 限制符号限制
  3. 按名称匹配
  4. @Resource

    1. 按名称匹配
    2. 按类型匹配
    3. 按限定符限制(如果按名称找到匹配则忽略)
    4. 我应该使用哪些注释(或组合)注入我的bean?

      1. 明确命名您的组件[@Component(&#34; beanName&#34;)]

      2. @Resourcename属性一起使用[@Resource(name =&#34; beanName&#34;)]

      3. 我为什么不使用@Qualifier

        除非您要创建类似bean的列表,否则请避免使用@Qualifier注释。例如,您可能希望使用特定的@Qualifier注释标记一组规则。这种方法可以很容易地将一组规则类注入到可用于处理数据的列表中。

        bean注入会减慢我的程序吗?

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


        参考: Spring Injection with @Resource, @Autowired and @Inject

答案 4 :(得分:38)

这是我从Spring 3.0.x Reference Manual得到的: -

  

提示

     

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

     

作为这种语义差异的特定结果,bean就是   自己定义为集合或地图类型不能注入   通过@Autowired,因为类型匹配不适用   给他们。对于这样的bean使用@Resource,参考具体的   按唯一名称收集或映射bean。

     

@Autowired适用于字段,构造函数和多参数   方法,允许缩小通过限定符注释   参数级别。相比之下,@ Resource仅支持字段   和bean属性setter方法,只有一个参数。作为一个   结果,如果您的注射目标是a,坚持使用限定符   构造函数或多参数方法。

答案 5 :(得分:20)

@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&amp; @Qualifier您需要设置特定的子实现 喜欢

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

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

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

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

#service.name=actualService
 service.name=stubbedService

希望能帮助某人:)

答案 6 :(得分:16)

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

答案 7 :(得分:6)

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

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

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

@Autowired / @Inject

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

@Resource

1。按名称匹配
2.按类型匹配
3.按预选赛限制(如果按名称找到匹配项则忽略)

答案 8 :(得分:4)

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

使用Spring 4.3+ @Autowired也能够做到这一点。

答案 9 :(得分:2)

@Resource通常由通过JNDI定义的高级对象使用。 <{1}}或@Autowired将被更常见的bean使用。

据我所知,这不是规范,甚至也不是惯例。这是标准代码使用这些注释的逻辑方式。

答案 10 :(得分:0)

在此注释: SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContextSpringBeanAutowiringSupport.processInjectionBasedOnServletContext 使用@Resource注释。所以,有区别。