Redian新闻
>
Spring探索|既生@Resource,何生@Autowired?

Spring探索|既生@Resource,何生@Autowired?

科技

阿里妹导读


本文主要针对Spring为什么要支持@Resource和@Autowired两个类似的注解做出了解答。

提到Spring依赖注入,大家最先想到应该是@Resource和@Autowired,很多文章只是讲解了功能上的区别,对于Spring为什么要支持两个这么类似的注解却未提到,属于知其然而不知其所以然。不知大家在使用这两个注解的时候有没有想过,@Resource又支持名字又支持类型,还要@Autowired干嘛,难道是Spring官方没事做了?
真的是没事做了吗?读了本文你将会了解到:
  1. @Resource和@Autowired来源
  2. Spring官方为什么会支持这两个功能如此相似的注解?
  3. 为什么@Autowired属性注入的时候Idea会曝出黄色的警告?
  4. @Resource和@Autowired推荐用法

来源

既然要弄清楚,就要先了解他们的身世。
@Resource 于 2006年5月11日随着JSR 250 发布 ,官方解释是:
Resource 注释标记了应用程序需要的资源。该注解可以应用于应用程序组件类,或组件类的字段或方法。当注解应用于字段或方法时,容器将在组件初始化时将所请求资源的实例注入到应用程序组件中。如果注释应用于组件类,则注释声明应用程序将在运行时查找的资源。
可以看到它类似一个定义,而由其他的组件或框架自由实现。
@Autowired 于 2007年11月19日随着Spring2.5发布,同时官方也对@Resource进行了支持。@Autowired的官方解释是:
将构造函数、字段、设置方法或配置方法标记为由 Spring 的依赖注入工具自动装配。
可以看到,@Autowired 是 Spring的亲儿子,而@Resource是Spring对它定义的一种实现,它们的功能如此相似。那么为什么要支持了@Resource,又要自己搞个@Autowired呢?
对此专门查了一下Spring2.5的官方文档,文档中有一段这么说到:
However, Spring 2.5 dramatically changes the landscape. As described above, the autowiring choices have now been extended with support for the JSR-250 @Resource annotation to enable autowiring of named resources on a per-method or per-field basis. However, the @Resource annotation alone does have some limitations. Spring 2.5 therefore introduces an @Autowired annotation to further increase the level of control.
大概的意思是说,Spring2.5 支持注解自动装配啦, 现已经支持JSR-250 @Resource 基于每个方法或每个字段的命名资源的自动装配,但是只有@Resource是不行的,我们还推出了“粒度”更大的@Autowired,来覆盖更多场景了。
嗯哼,那么官方说的“粒度”就是关键了,那“粒度”指的是什么呢”?

既生“@Resource”,何生“@Autowired”

要想找到粒度是什么,我们先从两个注解的功能下手
@Autowired
  • 类型注入

@Resource

  • 名字注入优先,找不到名字找类型

论功能的“粒度”,@Resource已经包含@Autowired了啊,“粒度”更大啊,难道是Spring2.5的时候还不是这样?我又去翻了下Spring2.5文档,上面明确的写到:

When using @Resource without an explicitly provided name, if no Spring-managed object is found for the default name, the injection mechanism will fallback to a type-match.
这不是和现在一样的吗,我此时凌乱了。那么“粒度”到底指的是什么?在混迹众多论坛后,其中stackoverflow的一段话引起了我的注意:
Both @Autowired and @Resource work equally well. But there is a conceptual difference or a difference in the meaning.
  • @Resource
     means get me a known resource by name. The name is extracted from the name of the annotated setter or field, or it is taken from the name-Parameter.
  • @Inject
     or 
    @Autowired
     try to wire in a suitable other component by type.

So, basically these are two quite distinct concepts. Unfortunately the Spring-Implementation of @Resource has a built-in fallback, which kicks in when resolution by-name fails. In this case, it falls back to the @Autowired-kind resolution by-type. While this fallback is convenient, IMHO it causes a lot of confusion, because people are.
大概的意思是:Spring虽然实现了两个功能类似的,但是存在概念上的差异或含义上的差异:
  • @Resource 这按名称给我一个确定已知的资源。
  • @Autowired 尝试按类型连接合适的其他组件。

但是@Resource当按名称解析失败时会启动。在这种情况下,它会按类型解析,引起概念上的混乱,因为开发者没有意识到概念上的差异,而是倾向于使用@Resource基于类型的自动装配。

原来Spring官方说的“粒度”是指“资源范围”,@Resource找寻的是确定的已知的资源,相当于给你一个坐标,你直接去找。@Autowired是在一片区域里面尝试搜索合适的资源。
所以上面的问题答案已经基本明确了。
Spring为什么会支持两个功能相似的注解呢?
  • 它们的概念不同,@Resource更倾向于找已知资源,而Autowired倾向于尝试按类型搜索资源。



  • 方便其他框架迁移,@Resource是一种规范,只要符合JSR-250规范的其他框架,Spring就可以兼容。

既然@Resource更倾向于找已知资源,为什么也有按类型注入的功能?

  • 个人猜测:可能是为了兼容从Spring切换到其他框架,开发者就算只使用Resource也是保持Spring强大的依赖注入功能。

Spring的区别对待

看到这相信大家对使用@Resource还是@Autowired有了自己的见解。在日常写代码中有个小细节不知道大家有没有注意到,使用@Autowired在属性上的时候Idea会曝出黄色的警告,并且推荐我们使用构造方法注入,而Resource就不会,这是为什么呢?警告如下:

为什么@Autowired在属性上的时候Idea会曝出黄色的警告,并且推荐我们使用构造方法注入?

其实Spring文档中已经给出了答案,主要有这几点:

1、声明不了常量的属性
基于属性的依赖注入不适用于声明为 final 的字段,因为此字段必须在类实例化时去实例化。声明不可变依赖项的唯一方法是使用基于构造函数的依赖项注入。
2、容易忽视类的单一原则
一个类应该只负责软件应用程序功能的单个部分,并且它的所有服务都应该与该职责紧密结合。如果使用属性的依赖注入,在你的类中很容易有很多依赖,一切看起来都很正常。但是如果改用基于构造函数的依赖注入,随着更多的依赖被添加到你的类中,构造函数会变得越来越大,代码开始就开始出现“异味”,发出明确的信号表明有问题。具有超过十个参数的构造函数清楚地表明该类有太多的依赖,让你不得不注意该类的单一问题了。因此,属性注入虽然不直接打破单一原则,但它却可以帮你忽视单一原则。
3、循环依赖问题
A类通过构造函数注入需要B类的实例,B类通过构造函数注入需要A类的实例。如果你为类 A 和 B 配置 bean 以相互注入,使用构造方法就能很快发现。
4、依赖注入强依赖Spring容器
如果您想在容器之外使用这的类,例如用于单元测试,不得不使用 Spring 容器来实例化它,因为没有其他可能的方法(除了反射)来设置自动装配的字段。

为什么@Resource没有呢?

在官方文档中,我没有找到答案,查了一些资料说是:@Autowired 是 Spring 提供的,一旦切换到别的 IoC 框架,就无法支持注入了. 而@Resource 是 JSR-250 提供的,它是 Java 标准,我们使用的 IoC 容器应该和它兼容,所以即使换了容器,它也能正常工作。

@Autowired和@Resource推荐用法

1. 什么场景用什么合适

记住一句话就行,@Resource倾向于确定性的单一资源,@Autowired为类型去匹配符合此类型所有资源
如集合注入,@Resource也是可以的,但是建议使用@Autowired。idea左侧的小绿标可以看出来,不建议使用@Resource注入集合资源,本质上集合注入不是单一,也是不确定性的。

2. @Autowired推荐用法

方法1 :使用构造函数注入(推荐)
原生版:
优雅版:使用lombok的@RequiredArgsConstructor+private final
方法2:set注入
原生版:
优雅版:使用lombok的@Setter

微信扫码关注该文公众号作者

戳这里提交新闻线索和高质量文章给我们。
相关阅读
Young Chinese Embrace Temple Visits to Evade Life’s PressuresDivorce Mediation Helping Couples Stay TogetherUser Sues Chinese Streaming Giant iQiyi for Curbing Access方法探索|一场树形 DP 深度游SRCNN、DRCN、FSRCNN、ESPCN、SRGAN、RED…你都掌握了吗?一文总结超分辨率分析必备经典模型(一)【Downtown/South End】【高级公寓】【全包】【半中介】【现房+九月排位】【$1810起】【Church Park|4月到10月入住排位來啦!|5分钟步行到伯克利/NEU|South End高级公寓|本科生首选】Chinese Professor Suspended For Racist, Homophobic Speech天赋“易昺(bǐng)”,创造历史!第二次徒步圣路,750公里葡萄牙之路+英国之路:D29~率先告捷Cape Cod -- South Yarmouth疗养院爆发 COVID 疫情,造成 5 人死亡,超过 90 人感染2030年加拿大减排目标与预测龙泉寺的一段往事干货分享 | How do you work under pressure?绝美挪威荷兰夏日之旅(一)哈当厄尔高原-沃尔令斯大瀑布Journalism Movie Hailed as ‘Courageous Start’ Wins Over Viewers【波士顿精品门户社区】【本科友好】【South End/Chinatown/Downtown】【$3195】【现房+9/1排位】生命科技领域创新机会探索|活动报名As Tourism Bounces Back, China’s Travel Bloggers Ride a ReboundChinese University Fires Professor Accused of Sexual HarassmentChinese Tourist Spot Accused of Copyright InfringementGuangzhou Postpartum Care Center Probed Over Surrogacy ClaimsStabbing Death on Train Raises Questions About Railway SecurityYoung Chinese Love Everything About Sweden. Except Living There.Spring循环依赖那些事儿(含Spring详细流程图)何时起,“骰子”不读shǎi,改读tóu了?Court Ruling Sparks Debate Over Promoting Work on Social MediaTop Sports Official Removed in Soccer Corruption Crackdown国际青少年创新创业大赛! International Youth Innovation&Entrepreneur Contest学完书本科学知识需上劳动大学TruEdu Academy 阅读俱乐部课程介绍 - Level 4 Future President别只会 SpringMVC 了!Spring 又官宣了一个更牛逼的替代框架!【基友票+30k 开卡奖励】Chase Southwest Premier 信用卡Conagen和Natáur达成合作,生产可持续天然牛磺酸Chase Southwest 联名卡 Pay Yourself Back (PYB) 功能简介:抵消年费&吃饭类别
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。