作者:汪军伍(处轩)

提到Spring依靠注入,咱们最早想到应该是@Resource和@Autowired,许多文章只是讲解了功用上的差异,对于Spring为什么要支撑两个这么相似的注解却未提到,属于知其然而不知其所以然。不知咱们在运用这两个注解的时分有没有想过,@Resource又支撑姓名又支撑类型,还要@Autowired干嘛,莫非是Spring官方没事做了?

真的是没事做了吗?读了本文你将会了解到:

  1. @Resource和@Autowired来源
  2. Spring官方为什么会支撑这两个功用如此相似的注解?
  3. 为什么@Autowired特点注入的时分Idea会曝出黄色的正告?
  4. @Resource和@Autowired引荐用法

来源

已然要弄清楚,就要先了解他们的身世。

@Resource 于2006年5月11日跟着JSR250发布 ,官方解说是:

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 @Resourceannotation to enable autowiring of named resources on a per-method or per-field basis. However, the @Resourceannotation alone does have some limitations. Spring 2.5 therefore introduces an @Autowiredannotation 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 @Autowiredand @Resourcework equally well. But there is a conceptual difference or a difference in the meaning.

  • @Resource means get me aknown 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 asuitable 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就不会,这是为什么呢?正告如下:

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

为什么@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注入调集资源,本质上调集注入不是单一,也是不确定性的。

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

2. @Autowired引荐用法

办法1 :运用结构函数注入(引荐)

原生版:

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

优雅版:运用lombok的@RequiredArgsConstructor+private final

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

办法2:set注入

原生版:

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

优雅版:运用lombok的@Setter

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