服务粉丝

我们一直在努力
当前位置:首页 > 财经 >

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

日期: 来源:阿里巴巴中间件收集编辑:汪军伍(处轩)

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

来源







Aliware

既然要弄清楚,就要先了解他们的身世。
@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”







Aliware

要想找到粒度是什么,我们先从两个注解的功能下手

@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 的区别对待







Aliware

看到这相信大家对使用@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 推荐用法







Aliware

1. 什么场景用什么合适

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

2. @Autowired推荐用法

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

相关阅读

  • 聊聊NDK开发那些事

  • / 今日科技快讯 /近日,中国移动(股价63.6港元,市值1.4万亿港元)在港交所发布2022年年度业绩公告,2022年实现营运收入为9373亿元,同比增长10.5%。公司股东应占利润为1254.59亿
  • 项目终于用上了插入式注解,真香!

  • 「 关注“石杉的架构笔记”,大厂架构经验倾囊相授 」文章来源:【公众号:码猿技术专栏】前言插入式注解处理器在《深入理解Java虚拟机》一书中有一些介绍(前端编译篇有提到),但一直
  • 徐州公交开展二季度线网重塑方案评审工作

  • 点击蓝字,一键关注 走进《公共交通资讯》,及时掌握公交领域的行业政策、管理理论、科技信息、专家观点和先进经验... ...全力做好“三提升”“五到位”“六板块”,柳州公交在经
  • 线上公开课 | NGS热点技术+应用案例,一次看个够

  • 初次上手做实验的老师们总有这些疑问:我要用哪些方法来回答我要解决的生物学问题?这些实验方法都是些啥?这些实验方法都能解释什么?......别着急,我们这一次带您了解测序实验的方
  • 为什么 Spring Boot 构造的jar包能直接运行?

  • 关注我,回复关键字“spring”,免费领取Spring学习资料。Spring Boot提供了一个插件spring-boot-maven-plugin用于把程序打包成一个可执行的jar包。在pom文件里加入这个插件即
  • 9个很酷的CMD命令

  • ipconfig功能:查询本机IP地址操作方法:只要在在打开的cmd命令界面中输入“ipconfig”就可以了。msg功能:向对方电脑发送一条文本提示操作方法:首先你要知道对方的IP地址,接下来输

热门文章

  • “复活”半年后 京东拍拍二手杀入公益事业

  • 京东拍拍二手“复活”半年后,杀入公益事业,试图让企业捐的赠品、家庭闲置品变成实实在在的“爱心”。 把“闲置品”变爱心 6月12日,“益心一益·守护梦想每一步”2018年四

最新文章

  • 查获水獭(tǎ)毛皮46张

  • 近日,北京海关所属大兴机场海关旅检现场在对一架进境航班监管时,发现1名旅客托运行李过机图像异常,行李内呈现大量不明团状物。经现场关员开箱查验,在该旅客托运及手提行李中发
  • Spring Cloud Alibaba 应用如何平滑迁移至 IPv6?

  • 背景AliwareIPv4 协议(后文简称 IPv4)为互联网的发展与普及做出了重要贡献,但近年来,随着应用程序、数据和 IT 服务的爆炸式增长。当初协议设计过程中用来描述 IP 地址所采用的
  • Java异常处理和最佳实践(含案例分析)

  • 01概述Aliware最近在代码CR的时候发现一些值得注意的问题,特别是在对Java异常处理的时候,比如有的同学对每个方法都进行 try-catch,在进行 IO 操作时忘记在 finally 块中关闭连
  • Spring探索丨既生@Resource,何生@Autowired?

  • 提到Spring依赖注入,大家最先想到应该是@Resource和@Autowired,很多文章只是讲解了功能上的区别,对于Spring为什么要支持两个这么类似的注解却未提到,属于知其然而不知其所以然
  • 【资料】美军的主要军事基地

  • 美国军费一直位居全球榜首,是中国的三倍,超过了排名前十的国家的总和。今天给大家分享美国在全球主要军事基地信息。1. 内利斯空军靶场州:内华达州军种:空军实际规模:4,531.25 平
  • Open AI ChatGPT推出插件系统!你做,他们帮推

  • ChatGPT 推出插件系统!!!他们推出了3个插件示例:网页浏览器:将Bing添加到对话中,现在可以访问互联网内容代码解释器:在沙盒和防火墙执行环境中添加一个实时的Python解释器检索:为你