我应该在 DI 中使用哪个注释,@Resource ( jsr250 ) 或@Autowired (Spring-specific)?
我过去都成功使用过,@Resource(name="blah")
并且@Autowired @Qualifier("blah")
我的直觉是坚持使用该@Resource
标签,因为它已被 jsr 人批准。
有人对此有强烈的想法吗?
我应该在 DI 中使用哪个注释,@Resource ( jsr250 ) 或@Autowired (Spring-specific)?
我过去都成功使用过,@Resource(name="blah")
并且@Autowired @Qualifier("blah")
我的直觉是坚持使用该@Resource
标签,因为它已被 jsr 人批准。
有人对此有强烈的想法吗?
两者@Autowired
(或@Inject
)@Resource
都同样有效。但是存在概念上的差异或含义上的差异
@Resource
意味着按名称给我一个已知的资源。该名称是从带注释的 setter 或字段的名称中提取的,或者是从 name-Parameter 中获取的。@Inject
或@Autowired
尝试按类型连接合适的其他组件。所以,基本上这是两个截然不同的概念。不幸的是,Spring-Implementation@Resource
有一个内置的回退,当按名称解析失败时会启动。在这种情况下,它会回@Autowired
退到 -kind 按类型解析。虽然这种回退很方便,但恕我直言,它会引起很多混乱,因为人们没有意识到概念上的差异,而是倾向于使用@Resource
基于类型的自动装配。
在春季 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
是一个弹簧注释。@Resource
正如您自己指出的那样,由 JSR-250 指定。所以后者是 Java 的一部分,而前者是 Spring 特定的。
因此,从某种意义上说,您的建议是正确的。我发现人们使用@Autowired
with@Qualifier
因为它更强大。从某个框架迁移到另一个框架被认为是非常不可能的,如果不是神话的话,尤其是在 Spring 的情况下。
我想强调@Jules对此问题的回答的一条评论。该评论带来了一个有用的链接:Spring Injection with @Resource、@Autowired 和 @Inject。我鼓励您完整阅读它,但这里是对其有用性的快速总结:
@Autowired
和@Inject
@Resource
显式命名您的组件 [@Component("beanName")]
@Resource
与name
属性 [@Resource(name="beanName")]一起使用
@Qualifier
?@Qualifier
除非您想创建类似 bean 的列表,否则请避免使用注释。例如,您可能希望使用特定@Qualifier
注释标记一组规则。这种方法使得将一组规则类注入到可用于处理数据的列表中变得很简单。
扫描特定的组件包[context:component-scan base-package="com.sourceallies.person"]
。虽然这将导致更多component-scan
配置,但它减少了您将不必要的组件添加到 Spring 上下文的机会。
这是我从Spring 3.0.x 参考手册中得到的:-
小费
如果您打算通过名称来表达注解驱动的注入,请不要主要使用@Autowired,即使在技术上能够通过@Qualifier 值引用bean 名称。相反,使用 JSR-250 @Resource 注释,它在语义上定义为通过其唯一名称标识特定目标组件,声明的类型与匹配过程无关。
作为这种语义差异的特定结果,本身定义为集合或映射类型的 bean 不能通过 @Autowired 注入,因为类型匹配不适用于它们。对此类 bean 使用 @Resource,通过唯一名称引用特定的集合或映射 bean。
@Autowired 适用于字段、构造函数和多参数方法,允许在参数级别通过限定符注释缩小范围。相比之下,@Resource 仅支持具有单个参数的字段和 bean 属性设置器方法。因此,如果您的注入目标是构造函数或多参数方法,请坚持使用限定符。
@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
希望对某人有所帮助:)
他们两个都一样好。使用 Resource 的好处是将来如果你想使用 Spring 以外的另一个 DI 框架,你的代码更改会简单得多。使用 Autowired 您的代码与弹簧 DI 紧密耦合。
当您从这两个注解的基类进行批判性分析时。您将意识到以下差异。
@Autowired
用于AutowiredAnnotationBeanPostProcessor
注入依赖项。
@Resource
用于CommonAnnotationBeanPostProcessor
注入依赖项。
即使它们使用不同的后处理器类,它们的行为也几乎相同。区别主要在于它们的执行路径,我在下面强调了这一点。
@Autowired / @Inject
1.按类型
匹配 2.按限定符
限制 3.按名称匹配
@Resource
1.按名称
匹配 2.按类型
匹配 3.按限定符限制(如果按名称找到匹配则忽略)
通过@Resource
您可以进行 bean 自注入,可能需要它来运行 bean 后处理器添加的所有额外逻辑,例如事务或安全相关的东西。
Spring 4.3+@Autowired
也可以做到这一点。
@Resource
通常由通过 JNDI 定义的高级对象使用。@Autowired
或@Inject
将被更常见的 bean 使用。
据我所知,它不是规范,甚至不是约定。这更像是标准代码使用这些注释的逻辑方式。
作为此处的注释:
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext
并且SpringBeanAutowiringSupport.processInjectionBasedOnServletContext
不适用于@Resource
注释。所以,有区别。