为什么IDEA提示不推荐@Autowired❓️如果使用@Resource呢❓️

ops/2025/2/3 4:25:27/

前言

在使用 Spring 框架时,依赖注入(DI)是一个非常重要的概念。通过注解,我们可以方便地将类的实例注入到其他类中,提升开发效率。@Autowired又是被大家最为熟知的方式,但很多开发者在使用 IntelliJ IDEA 时,常常看到 IDEA 提示不推荐使用@Autowired,这是为什么呢?今天讲一下我对于@Autowired字段注入的理解。

Autowired_3">1. 为什么不推荐使用@Autowired

1.1. 隐式依赖

@Autowired会根据类型自动注入依赖,可能导致依赖不明确。特别是在存在多个符合类型的候选对象时,可能会导致注入失败或错误地注入实例。

1.2. 循环依赖

@Autowired可能导致循环依赖,尤其在单例 Bean 中,虽然 Spring 有解决方案,但仍需额外处理。

1.3. 生命周期不透明

通过@Autowired注入的 Bean 由 Spring 管理,类无法显式了解其生命周期。相比之下,构造器注入可以显式管理依赖的生命周期。

1.4. 不符合不可变性原则

字段注入使得依赖关系在对象生命周期内可能发生变化,而构造器注入确保依赖在对象创建时设定,符合不可变性原则。

经常看到的争议点:不推荐使用@Autowired,所以就使用@Resource(使用@Resource时,IDEA不会有波浪线提示)。

AutowiredResource_25">2. @Autowired@Resource的基本用法

Autowired_26">2.1. @Autowired

@Autowired是 Spring 提供的注解,用于自动注入依赖项。Spring 会根据类型(默认情况下)或者名称(通过 @Qualifier)来自动注入所需的 Bean。

java">@Autowired
private UserService userService;

在这个例子中,Spring 会自动将 UserService 类型的 Bean 注入到 userService 属性中。

Resource_36">2.2. @Resource

@Resource 是 Java 规范的一部分,来自 javax/jakarta.annotation 包,它更注重按照名称来注入 Bean。默认情况下,它会尝试按名称匹配,但如果没有找到匹配的名称,再通过类型注入。

java">@Resource
private UserService userService;

@Autowired不同@Resource会首先查找名为userService的 Bean,如果找不到,再通过类型注入。

可以看出其实两者本质上是没有区别的,只是匹配顺序不一样。

AutowiredResource_49">3. @Autowired@Resource实测对比

假如有一个接口类,如下:

java">@Service
public interface UserService {// 用户服务...
}

两个实现类,如下:

java">@Component
public class UserServiceImpl implements UserService {// 实现细节
}@Component
public class AnotherUserServiceImpl implements UserService {// 另一个实现
}
Autowired_73">3.1. 使用@Autowired做测试

在测试接口里面加入@Autowired,如下:

java">/*** 测试接口*/
@RestController("test")
public class TestController {  @Autowiredprivate UserService userService;
}

启动项目,控制台输出错误,如下:

错误提示:需要一个bean,但是找到了两个bean。

修改之后指定具体的bean名,如下:

java">@RestController("test")
public class TestController {  @Autowired//	@Qualifier("userServiceImpl")  // 或者使用Qualifier来指定bean名private UserService userServiceImpl;
}

启动项目,项目正常启动,断点测试如下:

正常获取到需要的bean实例。

Resource_111">3.2. 使用@Resource做测试

在测试接口里面加入@Resource,如下:

java">/*** 测试接口*/
@RestController("test")
public class TestController {@Resourceprivate UserService userService;
}

启动项目,控制台输出错误,如下:

错误提示:需要一个bean,但是找到了两个bean。

修改之后指定具体的bean名,如下:

java">@RestController("test")
public class TestController {  @Resource// @Resource(name = "userServiceImpl")  // 或者使用name来指定bean名private UserService userServiceImpl;
}

启动项目,项目正常启动,断点测试如下:

正常获取到需要的bean实例。

可以看出实际上@Autowired@Resource的使用效果是一样的。(@Resource并不优于@Autowired,两者都是基于字段注入。甚至于在Spring框架中,@Autowired性能更好,例如:自动装配的细粒度控制 。)

4. 推荐注入的方式

构造器注入是推荐的首选方式,尤其在处理复杂依赖关系、不可变对象、单元测试等场景时,构造器注入非常有用。

4.1. 推荐原因
  • 显式依赖关系:构造器注入使依赖关系在对象创建时就显式地列出,代码更清晰。
  • 不可变性:依赖可以声明为 final,避免修改。
  • 避免循环依赖:能及时发现并避免循环依赖问题。
  • 明确依赖关系:构造器清晰暴露依赖,增强代码可读性。
4.2. 示例
java">@RestController("test")
public class TestController {private final UserService userService;public TestController(UserService userServiceImpl) {this.userService = userServiceImpl;}
}// 或者使用lombok简化代码。
@RestController("test")
@RequiredArgsConstructor
public class TestController {private final UserService userServiceImpl;
}

伪逻辑说明

  • 显式依赖关系
    应该关注的是,整个项目的代码规范,而不是针对具体的某一个类去优化,使用构造器注入。
  • 不可变性
    应该关注的是,合理的设计,项目中bean在初始时,如果使用@Autowired注入某个类,就应该不在初始化期间去修改它。
  • 避免循环依赖
    也是和项目的架构相关,如果无法中设计上避免,也可以通过代理和懒加载去解决。
  • 明确依赖关系
    如果项目类名命名规范,不使用相同的类名,或者使用一些前缀后缀去区分,也能够不影响依赖关系。

Autowired_193">5. 构造器一定优于@Autowired吗?

@Autowired在一些方面要优于构造器注入?

  1. 简化代码:自动注入依赖,无需手动编写构造器或 setter 方法,代码更简洁。

  2. 快速开发:灵活且快速,不需要修改构造函数,可以直接通过字段注入依赖。

  3. 自动依赖管理:Spring 自动管理依赖,简化了依赖的选择和注入过程。

  4. 避免构造函数冗长:对于依赖较多的类,字段注入避免了构造函数过长的问题。

结语

虽然 IDEA 提示不推荐使用 @Autowired,但这并不意味着它是一个糟糕的选择。不同的注入方式有其各自的优缺点,选择依赖注入方式时,应该根据项目规模、复杂性以及团队编码习惯来决定,而不是盲目跟随趋势。


http://www.ppmy.cn/ops/155219.html

相关文章

水稻和杂草检测数据集VOC+YOLO格式1356张2类别

数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):1356 标注数量(xml文件个数):1356 标注数量(txt文件个数):1356 标注…

RAG制作客服机器人,文档用表格还是QA问答对?

在使用RAG(Retrieval-Augmented Generation,检索增强生成)技术制作客服机器人时,表格和QA问答对这两种文档形式都有各自的优势,以下是它们的特点及适用情况分析: 表格形式 优点: 结构清晰&…

C#面试常考随笔4:int? 和 int的区别,以及int?的运用场景?

可空性 int?&#xff1a;它是int的可空类型&#xff0c;允许将null赋值给该变量。int?实际上是Nullable<int>的缩写形式&#xff0c;是一个可以为null的整数类型。例如&#xff1a;int? num2 null;或者int? num3 10;都是合法的。 内存分配与存储 int?&#xff…

4. 劲舞团python解法——2024年省赛蓝桥杯真题

问题描述&#xff1a;4.劲舞团 - 蓝桥云课 小蓝最近迷上了一款名为 “劲舞团” 的游戏&#xff0c;具体来说&#xff0c;只要按照游戏中给出的键位提示依次按出对应的键位&#xff0c;游戏人物便可以跟随节奏跳舞。对于连续的 K 次正确敲击&#xff0c;如果任意连续的两次敲击…

Linux《基础指令》

在之前的Linux《Linux简介与环境的搭建》当中我们已经初步了解了Linux的由来和如何搭建Linux环境&#xff0c;那么接下来在本篇当中我们就要来学习Linux的基础指令。在此我们的学习是包括两个部分&#xff0c;即指令和关于Linux的基础知识&#xff1b;因此本篇指令和基础知识的…

Python学习之旅:进阶阶段(五)数据结构-双端队列(collections.deque)

在 Python 的进阶学习过程中,数据结构的掌握至关重要。今天要介绍的双端队列(deque,即 double-ended queue),是一种非常实用的数据结构,Python 的collections模块中的deque类为我们提供了强大的双端队列操作功能。接下来,就一起深入了解双端队列吧。 一、什么是双端队列…

Brave132 编译指南 Windows 篇:部署 Node.js(五)

1. 引言 在 Brave 浏览器 132 版本的编译过程中&#xff0c;Node.js 扮演着至关重要的角色。作为一个基于 Chrome V8 引擎构建的 JavaScript 运行时环境&#xff0c;Node.js 赋予了开发者在服务器端执行 JavaScript 代码的能力。其非阻塞、事件驱动的架构使其特别擅长构建高性…

DeepSeek文生图模型Janus-Pro论文解读 —— 多模态AI的革命?

介绍 整个AI行业仍在适应最近发布的、震惊人工智能领域的 DeepSeek-R1。1月28日除夕当天的凌晨&#xff0c;DeepSeek 又发布了另一款出色的开源模型 Janus-Pro。这一次&#xff0c;它是一款能与其他顶级多模态模型相媲美的多模态人工智能模型。 在本文中&#xff0c;我们将解…