聊聊依赖注入注解@Resource和@Autowired
1. 前言
@Resource
和@Autowired
注解都可以在Spring Framework应用中进行声明式的依赖注入。而且面试中经常涉及到这两个注解的知识点。今天我们来总结一下它们。
2. @Resource
全称javax.annotation.Resource
,它属于JSR-250规范的一个注解,包含Jakarta EE(J2EE)中。Spring提供了对该注解的支持。我们来详细了解一下该注解的规则。
该注解使用在成员属性和setter方法上。默认情况下@Resource
按照名称注入,如果没有显式声明名称则按照变量名称或者方法中对应的参数名称进行注入。
如果我们希望在目标Bean中体现多态我们可以这样写:
/** * 多态的体现. * * @author felord.cn * @since 9 :26 */ @Component public class ResourceTest { @Resource private ApplicationRunner applicationRunner; @Resource private ApplicationRunner runner; // ... }
Qualifier 约束参见 Spring 注解 @Qualifier 详细解析
3. @Autowired
@Autowired
通常适用于构造函数,成员变量以及方法上。它的机制是这样的:
这个注解我们是需要好好聊聊的,日常使用频率相当高。
3.1 标注在构造上
通过在目标Bean的构造函数上标注就可以注入对应的Bean。
package cn.felord; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Component; /** * @author felord.cn * @since 9:26 **/ @Component public class AutowiredTest { private final ApplicationRunner applicationRunner; @Autowired public AutowiredTest(ApplicationRunner applicationRunner) { this.applicationRunner = applicationRunner; } }
从Spring Framework 4.3开始,
@Autowired
如果目标Bean只定义一个构造函数,则不再需要在该构造函数上添加@Autowired
注解。如果目标Bean有几个构造函数可用,并且没有主/默认构造函数,则必须至少有一个构造函数被@Autowired
标记,以指示Spring IoC容器使用哪个构造函数。
3.2 标注在成员变量上
和@Resource
一样,@Autowired
也可以标注到目标Bean的成员变量上。
/** * @author felord.cn * @since 9:26 **/ @Component public class AutowiredTest { @Autowired private ApplicationRunner applicationRunner; // ... }
3.3 标注到方法上
一般setter方法上使用的比较多。而且一个 @Autowired
支持注入多个参数。
/** * The type Autowired test. * * @author felord.cn * @since 9 :26 */ @Component public class AutowiredTest { private ApplicationRunner applicationRunner; private EmployeeMapper employeeMapper; private DepartmentMapper departmentMapper; /** * Sets application runner. * * @param applicationRunner the application runner */ @Autowired public void setApplicationRunner(ApplicationRunner applicationRunner) { this.applicationRunner = applicationRunner; } /** * 支持多参数 * * @param employeeMapper the employee mapper * @param departmentMapper the department mapper */ @Autowired public void prepare(EmployeeMapper employeeMapper, DepartmentMapper departmentMapper) { this.employeeMapper = employeeMapper; this.departmentMapper = departmentMapper; } }
你以为这就完了?下面这种方式估计大多数人并没有在意过。
/** * The type Autowired test. * * @author felord.cn * @since 9 :26 */ @Component public class AutowiredTest { // 注入 数组 @Autowired private MovieCatalog[] movieCatalogs; private Map<String, Movie> movies; private Set<CustomerPreferenceDao> customerPreferenceDaos; // 注入 set @Autowired public MovieRecommender(Set<CustomerPreferenceDao> customerPreferenceDaos) { this.customerPreferenceDaos = customerPreferenceDaos; } // 注入 map @Autowired public void setMovieCatalogs(Map<String, Movie> movies) { this.movies = movies; } // ... }
可以把Bean注入目标Bean的数组、集合容器中去。默认情况下,当给定注入点没有匹配的候选Bean可用时,自动装配将失败。至少应有一个匹配元素。
如果您希望元素按照特定顺序排序,则元素Bean可以实现
org.springframework.core.Ordered
接口或者对应注解@Order
或标准@Priority
。基于某些机制不建议使用注解方式来排序,否则无法达到预期期望,推荐使用接口Ordered
。
3.4 装配可选
@Resource
没有提供可选择装配的特性,一旦无法装配则会抛出异常;而@Autowired
提供了required
属性(默认值为true
)以避免这种情况,设置@Autowired
为false
。
/** * The type Autowired test. * * @author felord.cn * @since 9 :26 */ @Component public class AutowiredTest { // 一旦找不到 movieFinder 不会异常 而初始化为 null @Autowired(required = false) private MovieFinder movieFinder; // ... }
这里也有骚操作,你可以忽略required
属性。通过 Java 8的 java.util.Optional
来表明候选Bean可选。
/** * The type Autowired test. * * @author felord.cn * @since 9 :26 */ @Component public class AutowiredTest { public class SimpleMovieLister { // 使用 Optional 表明候选Bean可选 @Autowired public void setMovieFinder(Optional<MovieFinder> movieFinder) { // ... } }
从Spring 5.0开始,您还可以使用@Nullable
注解,这个注解可以你自己实现检测逻辑或者直接使用 JSR-305提供的javax.annotation.Nullable
。
/** * The type Autowired test. * * @author felord.cn * @since 9 :26 */ @Component public class AutowiredTest { public class SimpleMovieLister { // 使用 @Nullable 注解表明候选Bean可选 @Autowired public void setMovieFinder(@Nullable MovieFinder movieFinder) { // ... } }
4. @Inject
从Spring 3.0开始,Spring提供对JSR-330标准注解(依赖注入)的支持。 你需要引入依赖:
<dependency> <groupId>javax.inject</groupId> <artifactId>javax.inject</artifactId> <version>1</version> </dependency>
然后你就可以使用相关的注解来进行依赖注入了,其中主要注解为@javax.inject.Inject
。大部分情况下该注解都可以代替@Autowired
使用,但@Inject
没有required
属性,不过它也可以与java.util.Optional
或使用@Nullable
来达到同样的效果。
大部分情况下没有人喜欢额外引入Jakarta EE依赖来使用一个已经拥有的功能,Spring堵死了Jakarta EE依赖注入的生态。
5. 总结
@Resource
和@Autowired
的优先级顺序不同(参见上图),另外@Resource
属于 Jakarta EE规范而@Autowired
属于Spring
范畴,@Resource
无法使用在构造参数中,@Autowired
支持required
属性。从面向对象来说,@Resource
更加适用于多态性的细粒度注入,而@Autowired
更多专注于多态的单例注入。@Inject
则没必要过多讨论,只作为一个添头。好了今天就到这里,多多关注:码农小胖哥,更多干货知识分享。
关注公众号:Felordcn获取更多资讯
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
如何写好一个 Spring 组件
背景 Spring 框架提供了许多接口,可以使用这些接口来定制化 bean ,而非简单的 getter/setter 或者构造器注入。细翻 Spring Cloud Netflix、Spring Cloud Alibaba 等这些构建在 Spring Framework 的成熟框架源码,你会发现大量的扩展 bean 例如 Eureka 健康检查 package org.springframework.cloud.netflix.eureka; public class EurekaHealthCheckHandler implements InitializingBean {} Seata Feign 配置 package com.alibaba.cloud.seata.feign; public class SeataContextBeanPostProcessor implements BeanPostProcessor {} 代码示例 DemoBean @Slf4j public class DemoBean implements InitializingBean { publi...
- 下一篇
xmake v2.3.4 发布,更加完善的工具链支持
为了让xmake更好得支持交叉编译,这个版本我重构了整个工具链,使得工具链的切换更加的方便快捷,并且现在用户可以很方便地在xmake.lua中扩展自己的工具链。 关于平台的支持上,我们新增了对*BSD系统的支持,另外,此版本还新增了一个ninja主题风格,实现类似ninja的编译进度显示,例如: 项目源码 官方文档 新特性介绍 工具链改进 工具链和平台完全分离 之前的版本,平台和工具链绑定的过于紧密,例如xmake f -p windows平台,默认只能使用msvc的编译,想要切到clang或者其他编译器,就只能走交叉编译平台:xmake f -p cross。 但是这样的话,一些windows平台特有的设置就丢失了,而且用户也没法使用if is_plat("windows") then来判断windows平台做特定的设置。 其实平台和工具链是完全可以独立开来的,新版本经过重构后,即使是windows平台以及其他任何平台,也可以方便快速的切换到clang, llvm等其他工具链。 $ xmake f -p windows --toolchain=clang 内置工具链 虽然xma...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- 2048小游戏-低调大师作品
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- MySQL8.0.19开启GTID主从同步CentOS8
- 设置Eclipse缩进为4个空格,增强代码规范
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池