【问题标题】:@Resource vs @Autowired@Resource 与 @Autowired
【发布时间】:2011-05-04 20:34:38
【问题描述】:

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

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

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

【问题讨论】:

  • 仅供参考 - 我删除了“更新”,它应该作为一个单独的问题提出。根据这条被拒绝的评论,“此编辑偏离了帖子的原始意图。即使是必须进行重大更改的编辑也应努力保持帖子所有者的目标”

标签: java spring dependency-injection annotations autowired


【解决方案1】:

当你从这两个注解的基类进行批判性分析时。你会意识到以下区别。

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

即使它们使用不同的后处理器类,它们的行为也几乎相同。 区别主要在于它们的执行路径,我在下面强调了这一点。

@Autowired / @Inject

1.按类型匹配
2.限定条件
3.按名称匹配

@Resource

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

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

      • 是的,这应该是一个可以接受的答案。例如,如果您有一个 @Resource 注释字段,并且字段名称与容器中 bean 的 id 匹配,那么如果它们的类型不同,Spring 将抛出 org.springframework.beans.factory.BeanNotOfRequiredTypeException - 这是因为 bean 首先在 @Resource 注释中按名称匹配,不是按类型。但是如果属性的名称与 bean 的名称不匹配,那么 Spring 将按类型连接它们。
      • 当您尝试使用简单的 MAP 时,您可以参考另一篇说明两者之间区别的帖子。 stackoverflow.com/questions/13913752/…
      • +1 用于实际回答问题,而不是像接受的答案那样简单地推荐完全不同的“最佳实践”。我还发现了这篇博文,它显示了所有三种注释样式的几种常见场景的结果,很有帮助:blogs.sourceallies.com/2011/08/…
      • 读者请在此处找到@Jules 所指文章的摘要:stackoverflow.com/a/23887596/363573
      • 这意味着:当你想注入一个 Map/List bean 时,@Autowire 不能也不会工作。在这种情况下,您将不得不使用 @Resource
      【解决方案4】:

      @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
      

      希望对某人有所帮助:)

      【讨论】:

        【解决方案5】:

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

        提示

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

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

        @Autowired 适用于字段、构造函数和多参数 方法,允许通过限定符注释在 参数级别。相比之下,@Resource 仅支持字段 和带有单个参数的 bean 属性设置器方法。作为一个 因此,如果您的注入目标是 构造函数或多参数方法。

        【讨论】:

        【解决方案6】:

        我想强调来自@Julesthis answer 对这个问题的评论。该评论带来了一个有用的链接:Spring Injection with @Resource, @Autowired and @Inject。我鼓励您完整地阅读它,但这里是对其有用性的快速总结:

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

        @Autowired@Inject

        1. 按类型匹配
        2. 限定符限制
        3. 按名称匹配

        @Resource

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

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

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

        2. @Resourcename 属性一起使用[@Resource(name="beanName")]

        为什么我不应该使用@Qualifier

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

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

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


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

        【讨论】:

          【解决方案7】:

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

          据我所知,它既不是规范,也不是惯例。这更像是标准代码使用这些注释的合乎逻辑的方式。

          【讨论】:

            【解决方案8】:

            这里要注意: SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContextSpringBeanAutowiringSupport.processInjectionBasedOnServletContext @Resource 注释一起使用。所以,还是有区别的。

            【讨论】:

              【解决方案9】:

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

              【讨论】:

              • 这可能看起来像一个愚蠢的问题,但是当您使用这种注入方式时,您是否需要foo 的公共设置器或SomeBean 中带有Foo 参数的构造函数?
              • @Snekse - 得到我的答案:stackoverflow.com/questions/3536674/…
              • 不。你不需要这些。只是场。 (Spring 通过反射填充它)
              • @Bozho 这个答案实际上并没有显示@Resource@Autowired 的区别,实际答案是@Ichthyo 发布的那个,我认为这个必须更新。
              • 是的。事实上,我有时会通过提供更好的替代方法来回答问题。但为了完整起见,我在下面包含了原始问题的答案
              【解决方案10】:

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

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

              【讨论】:

              • +1,因为@Autowired@Qualifier 确实比JSR 标准的@Resource 注释更强大(考虑可选的依赖关系,例如@Autowired(required=false)。你不能用@Resource)
              【解决方案11】:

              两者都一样好。使用 Resource 的好处是将来如果你想使用 Spring 以外的另一个 DI 框架,你的代码更改会简单得多。使用 Autowired 您的代码与弹簧 DI 紧密耦合。

              【讨论】:

              • 永远不会发生。即使确实如此 - 对注释名称进行查找/替换也将是您遇到的最少问题。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-06-15
              • 1970-01-01
              • 2014-12-14
              • 2016-02-18
              • 2015-09-28
              相关资源
              最近更新 更多