我应该在DI中使用哪个注释,@ (jsr250)或@ autowired (Spring-specific) ?
我已经成功地使用这两个在过去,@Resource(name="blah")和@Autowired @Qualifier("blah")
@Resource(name="blah")
@Autowired @Qualifier("blah")
@Resource
他们两个都一样好。使用Resource的优势在于,如果将来您想使用spring以外的另一个DI框架,您的代码更改将会简单得多。使用Autowired您的代码与spring DI紧密耦合。
主要的区别是,@Autowired是一个spring注释。而@Resource是由JSR-250指定的,正如你自己指出的那样。因此,后者是Java的一部分,而前者是Spring特有的。
@Autowired
因此,在某种意义上,你的建议是正确的。我发现人们使用@Autowired和@Qualifier,因为它更强大。从一个框架转移到另一个框架被认为是不太可能的,特别是在Spring的情况下。
@Qualifier
在3.0之前的春季版本中,哪种都不重要。
在spring 3.0中,支持标准(jsr - 330)注释@javax.inject.Inject -使用它,并结合@Qualifier。注意,spring现在也支持@javax.inject.Qualifier元注释:
@javax.inject.Inject
@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;
这减少了字符串名称的使用,字符串名称可能会拼写错误,并且更难维护。
至于最初的问题:两者都没有指定注释的任何属性,而是按类型执行注入。区别在于:
@Autowired(或@Inject)和@Resource工作得同样好。但在概念上或意义上存在差异
@Inject
基本上这是两个截然不同的概念。不幸的是,@Resource的Spring-Implementation有一个内置的回退,当按名称解析失败时就会启动。在这种情况下,它按类型回落到__abc1类解析。虽然这种回退很方便,但恕我直言,它会引起很多混乱,因为人们没有意识到概念上的差异,并倾向于使用@Resource来进行基于类型的自动装配。
请注意: SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext和SpringBeanAutowiringSupport.processInjectionBasedOnServletContext 不使用@Resource注释。所以有区别。
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext
SpringBeanAutowiringSupport.processInjectionBasedOnServletContext
这是我从Spring 3.0。x参考手册中得到的:-
提示 如果您打算通过名称来表示注释驱动的注入,请执行 不主要使用@Autowired,即使技术上有能力 通过@Qualifier值引用bean名。相反,使用 JSR-250 @Resource注释,它在语义上定义为 的惟一名称标识特定的目标组件 声明的类型与匹配进程无关 作为语义差异的具体结果,bean是 定义为集合或映射类型的本身不能被注入 通过@Autowired,因为类型匹配不能正确应用 给他们。对于这样的bean使用@Resource,引用特定的 @Autowired应用于字段、构造函数和多参数 方法,允许通过限定符注释进行缩小 参数的水平。相比之下,@Resource只支持字段 和带有单个参数的bean属性setter方法。作为一个 结果,如果你的注入目标是
提示
作为语义差异的具体结果,bean是 定义为集合或映射类型的本身不能被注入 通过@Autowired,因为类型匹配不能正确应用 给他们。对于这样的bean使用@Resource,引用特定的
@Autowired应用于字段、构造函数和多参数 方法,允许通过限定符注释进行缩小 参数的水平。相比之下,@Resource只支持字段 和带有单个参数的bean属性setter方法。作为一个 结果,如果你的注入目标是
@Resource通常由通过JNDI定义的高级对象使用。@Autowired或@Inject将被更常见的bean使用。
据我所知,这不是一个规范,甚至不是一个约定。这更像是标准代码使用这些注释的逻辑方式。
我想强调@Jules对这个答案对这个问题的一个评论。注释带来了一个有用的链接:使用@Resource, @Autowired和@Inject进行Spring注入。我鼓励你把它通读一遍,但这里有一个简单的总结:
@Autowired和@Inject
明确命名组件[@Component("beanName")]
使用@Resource和name属性[@Resource(name="beanName")]
name
避免使用@Qualifier注释,除非你想创建一个类似bean的列表。例如,你可能想用特定的@Qualifier注释标记一组规则。这种方法使将一组规则类注入可用于处理数据的列表变得简单。
扫描组件[context:component-scan base-package="com.sourceallies.person"]的特定包。虽然这会导致更多的component-scan配置,但它减少了你将不必要的组件添加到Spring上下文的机会。
[context:component-scan base-package="com.sourceallies.person"]
component-scan
< >强引用:< / >强 使用@Resource, @Autowired和@Inject进行Spring注入
@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你需要设置特定的子实现 像< / 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注入依赖项 尽管它们使用不同的后置处理器类,但它们的行为几乎相同。 关键的区别在于它们的执行路径,我在下面强调了这一点
AutowiredAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor
@Autowired / @Inject