Resource/Autowired注解区别?

Resource/Autowired注解区别?

马草原 893 2022-08-27

Resource/Autowired注解区别?

提到Spring依赖注入,大家最先想到应该是@Resource@Autowired,很多文章只是讲解了功能上的区别,对于Spring为什么要支持两个这么类似的注解却未提到。他们具体有什么区别?Spring官方为什么会支持这两个功能如此相似的注解?使用@Autowired属性注入的时候IDEA又为什么会曝出黄色的警告?

一个小小的黄色警告可能很多人根本不会在意,但是最近读了《整洁代码之道》《重构》《阿里巴巴代码规范》等书后有很强的代码整洁意识,真的是一个黄色警告都看不下去🙄。那么这里就来好好了解一下他们到底有什么区别?为什么会警告⚠。

@Resource和@Autowired来源

@Resource

@Resource 于 2006年5月11日随着JSR 250 发布 ,官方解释是:
Resource 注释标记了应用程序需要的资源。该注解可以应用于应用程序组件类,或组件类的字段或方法。当注解应用于字段或方法时,容器将在组件初始化时将所请求资源的实例注入到应用程序组件中。如果注释应用于组件类,则注释声明应用程序将在运行时查找的资源。

可以看到它是一种规范,而具体实现是由其他的组件或框架自由实现的。

@Autowired

@Autowired 于 2007年11月19日随着Spring2.5发布,同时官方也对@Resource进行了支持
@Autowired的官方解释是:
将构造函数、字段、设置方法或配置方法标记为由 Spring 的依赖注入工具自动装配。

可以看到,@Autowired 是 Spring的亲儿子,而@Resource是Spring对JSR 250规范的的一种实现,它们的功能如此相似。

那么为什么Spring又要自己搞个@Autowired呢?

Spring虽然实现了两个功能类似的,但是存在概念上的差异或含义上的差异:

  • @Resource 着按名称给我一个确定已知的资源。
  • @Autowired 尝试按类型连接合适的其他组件。

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

@Resource找寻的是确定的已知的资源,相当于给你一个坐标,你直接去找。
@Autowired是在一片区域里面尝试搜索合适的资源。

Autowired和Resource的区别

  • 它们的概念不同,@Resource更倾向于找已知资源,而@Autowired倾向于尝试按类型搜索资源。
  • 方便其他框架迁移,@Resource是一种规范,只要符合JSR-250规范的其他框架,Spring就可以兼容。

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

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

为什么使用@Autowired会黄色警告

在日常写代码中有个小细节不知道大家有没有注意到,使用@Autowired属性上的时候IDEA会曝出黄色的警告,并且推荐我们使用构造方法注入,而@Resource就不会,这是为什么呢?

警告如下:

resource

为什么推荐我们使用构造方法注入?

  • 声明不了常量的属性

基于属性的依赖注入不适用于声明为 final 的字段,因为此字段必须在类实例化时去实例化。声明不可变依赖项的唯一方法是使用基于构造函数的依赖项注入。

  • 容易忽视类的单一原则

一个类应该只负责软件应用程序功能的单个部分,并且它的所有服务都应该与该职责紧密结合。如果使用属性的依赖注入,在你的类中很容易有很多依赖,一切看起来都很正常。但是如果改用基于构造函数的依赖注入,随着更多的依赖被添加到你的类中,构造函数会变得越来越大,代码开始就开始出现“异味”,发出明确的信号表明有问题。具有超过十个参数的构造函数清楚地表明该类有太多的依赖,让你不得不注意该类的单一问题了。因此,属性注入虽然不直接打破单一原则,但它却可以帮你忽视单一原则。

  • 循环依赖问题

A类通过构造函数注入需要B类的实例,B类通过构造函数注入需要A类的实例。如果你为类 A 和 B 配置 bean 以相互注入,使用构造方法就能很快发现。

  • 依赖注入强依赖Spring容器

如果您想在容器之外使用这的类,例如用于单元测试,不得不使用 Spring 容器来实例化它,因为没有其他可能的方法(除了反射)来设置自动装配的字段。

为什么@Resource没有警告?

@Autowired是Spring提供的,一旦切换到别的IoC框架,就无法支持注入了. 而@ResourceJSR-250提供的,它是Java标准、规范,我们使用的IoC容器应该和它兼容,所以即使换了容器,它也能正常工作。

spring-1678846696370