@Resource vs @Autowired

我应该在DI中使用哪个注释,@ (jsr250)或@ autowired (Spring-specific) ?

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

我的直觉是坚持使用@Resource标签,因为它已经被jsr的人批准了 有人对此有强烈的想法吗?< / p >
277230 次浏览

他们两个都一样好。使用Resource的优势在于,如果将来您想使用spring以外的另一个DI框架,您的代码更改将会简单得多。使用Autowired您的代码与spring DI紧密耦合。

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

因此,在某种意义上,你的建议是正确的。我发现人们使用@Autowired@Qualifier,因为它更强大。从一个框架转移到另一个框架被认为是不太可能的,特别是在Spring的情况下。

在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允许你将它标记为非强制的。

@Autowired(或@Inject)和@Resource工作得同样好。但在概念上或意义上存在差异

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

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

请注意: SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContextSpringBeanAutowiringSupport.processInjectionBasedOnServletContext 使用@Resource注释。所以有区别。

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

提示

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

作为语义差异的具体结果,bean是 定义为集合或映射类型的本身不能被注入 通过@Autowired,因为类型匹配不能正确应用 给他们。对于这样的bean使用@Resource,引用特定的

@Autowired应用于字段、构造函数和多参数 方法,允许通过限定符注释进行缩小 参数的水平。相比之下,@Resource只支持字段 和带有单个参数的bean属性setter方法。作为一个 结果,如果你的注入目标是

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

据我所知,这不是一个规范,甚至不是一个约定。这更像是标准代码使用这些注释的逻辑方式。

我想强调@Jules这个答案对这个问题的一个评论。注释带来了一个有用的链接:使用@Resource, @Autowired和@Inject进行Spring注入。我鼓励你把它通读一遍,但这里有一个简单的总结:

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

@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上下文的机会。


< >强引用:< / >强 使用@Resource, @Autowired和@Inject进行Spring注入

@Autowired + @Qualifier将只与spring DI一起工作,如果你想在未来使用一些其他DI @Resource是一个不错的选择。

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

例如< p >: 如果你有一个具有多个实现的接口,如

. 0
interface parent {


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


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


}

与@Autowired &@Qualifier你需要设置特定的子实现 像< / p >

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

它不提供占位符,而@资源,你可以把占位符和使用属性文件注入特定的子实现,如

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

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

#service.name=actualService
service.name=stubbedService

希望这能帮助到一些人:)

使用@Resource你可以做bean自我注入,它可能是为了运行bean后处理器添加的所有额外逻辑,比如事务或安全相关的东西。

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

当您从这两个注释的基类进行严格分析时。您将认识到以下不同之处。

@Autowired使用AutowiredAnnotationBeanPostProcessor注入依赖项 @Resource使用CommonAnnotationBeanPostProcessor注入依赖项 尽管它们使用不同的后置处理器类,但它们的行为几乎相同。 关键的区别在于它们的执行路径,我在下面强调了这一点

@Autowired / @Inject
< p > 1。匹配类型
2.限定符
3.匹配名称

@Resource
< p > 1。匹配名称
2.匹配类型
3.通过限定符限制(如果通过名称找到匹配则忽略)