Spring Boot中的依赖注入是如何工作

devtools/2025/1/13 13:18:08/

Spring Boot 中的依赖注入(Dependency Injection,简称 DI)是通过 Spring 框架的核心机制——控制反转(Inversion of Control,IOC)容器来实现的。Spring Boot 基于 Spring Framework,在应用中自动进行对象的创建、管理、注入等工作,开发者只需要声明依赖关系,Spring 会自动将这些依赖注入到类中。

依赖注入的工作原理

在 Spring Boot 中,依赖注入的核心概念是:通过容器( ApplicationContext)来管理和注入类的依赖。Spring 通过 注解来声明和管理这些依赖。

主要的注解有:

  • @Component / @Service / @Repository / @Controller:这些注解用于标记一个类为 Spring 管理的 Bean。
  • @Autowired:用于标注类中的依赖变量,告诉 Spring 自动注入相应的 Bean。
  • @Configuration@Bean:用于配置类及其方法,生成和管理 Bean。

依赖注入的工作流程

  1. Bean 定义:通过注解将类标记为 Spring 管理的 Bean(如 @Service@Component 等)。
  2. 自动注入:使用 @Autowired 注解将需要的 Bean 注入到类中。Spring Boot 会根据类型自动查找匹配的 Bean 并注入。
  3. 容器管理:Spring 会自动扫描指定的包(通常是启动类所在的包及其子包),根据注解发现类,并把它们放入 IOC 容器中进行管理。
  4. 生命周期管理:Spring 管理这些 Bean 的生命周期,包括实例化、依赖注入、初始化等。

代码案例:Spring Boot 中的依赖注入

1. 创建 Bean 类
java">package com.hk.service;import org.springframework.stereotype.Service;@Service
public class UserService {public String getUserInfo(String userId) {return "User的id是: " + userId;}
}
  • @Service 注解将 UserService 类标记为一个 Spring 管理的 Bean。Spring Boot 会将 UserService 作为一个 Bean 加入到 Spring 容器中进行管理。
2. 依赖注入到其他类
java">package com.hk.controller;import com.hk.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;@RestController
public class UserController {private final UserService userService;// 通过构造器注入 UserService@Autowiredpublic UserController(UserService userService) {this.userService = userService;}@GetMapping("/user/{userId}")public String getUserInfo(@PathVariable String userId) {// 使用注入的 UserService 实例return userService.getUserInfo(userId);}
}
  • @RestController 注解用于定义一个 REST 控制器,是一个处理 HTTP 请求的组件。
  • @Autowired 注解用于自动注入UserService实例。在上面的代码中,依赖注入是通过构造器进行的。
    • 构造器注入 是推荐的方式,它可以确保依赖关系在对象创建时就已经完全注入。构造器注入具有更高的可测试性和更好的不可变性。
3. 自动注入的其他方式

除了构造器注入,Spring 还支持 字段注入setter 注入

a. 字段注入
java">@RestController
public class UserController {@Autowiredprivate UserService userService;  // 字段注入@GetMapping("/user/{userId}")public String getUserInfo(@PathVariable String userId) {return userService.getUserInfo(userId);}
}
  • 字段注入是将 @Autowired 注解直接放在字段上,Spring 会自动注入对应类型的 Bean。
  • 这种方式代码简洁,但缺点是无法控制依赖注入的顺序,且不容易进行单元测试。
b. Setter 注入
java">@RestController
public class UserController {private UserService userService;@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}@GetMapping("/user/{userId}")public String getUserInfo(@PathVariable String userId) {return userService.getUserInfo(userId);}
}
  • Setter 注入通过 @Autowired 注解标记在 setter 方法上,Spring 会调用这个方法来注入依赖。
  • 适用于某些需要选择性注入的场景,或者对于可选的依赖进行注入。
4. 使用 @Qualifier 注解解决多个 Bean 的冲突

如果有多个类型相同的 Bean,Spring 会根据类型来进行注入,但如果类型不唯一,会抛出 NoUniqueBeanDefinitionException 异常。在这种情况下,我们可以使用 @Qualifier 注解来指定注入哪一个 Bean。

假设我们有两个 UserService 的实现类:

java">package com.hk.service;import org.springframework.stereotype.Service;@Service("userServiceV1")
public class UserServiceV1 implements UserService {public String getUserInfo(String userId) {return "User V1 的id是: " + userId;}
}@Service("userServiceV2")
public class UserServiceV2 implements UserService {public String getUserInfo(String userId) {return "User V2 的id是: " + userId;}
}

使用 @Qualifier 来指定注入的 Bean:

java">package com.hk.controller;import com.hk.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;@RestController
public class UserController {private final UserService userService;@Autowiredpublic UserController(@Qualifier("userServiceV1") UserService userService) {this.userService = userService;}@GetMapping("/user/{userId}")public String getUserInfo(@PathVariable String userId) {return userService.getUserInfo(userId);}
}
  • 通过 @Qualifier("userServiceV1") 注解,我们指定了要注入 userServiceV1 Bean。
5. @Primary 注解

如果有多个类型相同的 Bean,且不想每次都使用 @Qualifier 来指定注入哪个 Bean,可以使用 @Primary 注解来标记一个优先注入的 Bean。

java">package com.hk.service;import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;@Service
@Primary
public class UserServiceV1 implements UserService {public String getUserInfo(String userId) {return "User V1 的id是: " + userId;}
}
  • @Primary 注解标记的 Bean 将会是默认注入的 Bean,Spring 会优先选择它进行注入。

总结

在 Spring Boot 中,依赖注入的工作原理是通过 Spring 容器管理对象的生命周期,并将所需的依赖注入到类中。常见的注入方式包括构造器注入、字段注入和 setter 注入。Spring 使用 @Autowired 注解来自动注入依赖,通过 @Component 和其衍生注解(如 @Service@Repository 等)标记 Bean。还可以通过 @Qualifier@Primary 注解来解决多个 Bean 的冲突问题。


http://www.ppmy.cn/devtools/150154.html

相关文章

AI开发 - 算法基础 递归 的概念和入门(三)递归的进阶学习

前面我们通过2篇文章,一起了解了 递归,以及使用递归来解决汉诺塔问题。今天我们在这个基础上,进一步地熟悉和学习递归。 这篇学习笔记将涵盖递归的基本概念、应用、优化技巧、陷阱及与迭代的对比,并通过具体的 Python 代码示例和…

Github出现复杂问题 无法合并 分支冲突太多 如何复原

目录 问题再现 解决思路 当然我所指的是在 main 分支开一个新的分支 删除本地文件夹 重新克隆 开一个新分支 切换分支 下载远程分支 文件覆盖 合并到主分支 ​​​​​​​问题再现 太复杂了 无法更改 编译器现状 全部崩溃了 无法更改 即使创建一个新的分支也无济于…

Pytest-Bdd-Playwright 系列教程(完结篇):本框架的功能参数说明

Pytest-Bdd-Playwright 系列教程(完结篇):本框架的功能参数说明 简介1. 浏览器设置2. 环境与设备配置3. 存储状态管理4. 测试用例筛选5. 并行与重试控制6. 报告生成与输出格式7. 其他功能附录:参数说明表 简介 本框架支持多种浏览…

从攻击视角探讨ChatGPT对网络安全的影响

ChatGPT是OpenAI 发布的基于人工智能的对话机器人,上线短短2个月活跃用户就突破了1亿,成为全球关注的焦点。ChatGPT可以自动化地处理对话,可以通过基于自然语言处理技术的模型、情景模型和语言模型来自动生成文章,甚至可以按照用户…

Kafka优势剖析-流处理集成

目录 1. Kafka Streams API 1.1 什么是 Kafka Streams API? 1.2 Kafka Streams 的工作原理 1.3 Kafka Streams 的优势 1.4 Kafka Streams 的典型应用场景 2. KSQL 2.1 什么是 KSQL? 2.2 KSQL 的工作原理 2.3 KSQL 的优势 Kafka 的流处理能力是其…

【数据库】四、数据库管理与维护

文章目录 四、数据库管理与维护1 安全性管理2 事务概述3 并发控制4 备份与恢复管理 四、数据库管理与维护 1 安全性管理 安全性管理是指保护数据库,以避免非法用户进行窃取数据、篡改数据、删除数据和破坏数据库结构等操作 三个级别认证: 服务器级别…

C# 继承(接口)

接口 如果一个类派生与一个接口,它就会执行某些函数。并不是所有的面向对象语言都支持接口。 熟悉COM的开发人员应注意,尽管在概念上C#接口类似于COM接口,但他们是不筒的,底层的结构不筒。比如,C#接口并不派生于IUnko…

安卓开发动画

1.gif图片动画 边缘会有锯齿 2.json动画 用lottie json文件动画 实现 Android Studio使用lottie,加载json文件,实现动画效果_android 加载json动画-CSDN博客 遇到的坑 1.不播放,可能因为设置了图片(跟动画一样的图片&#xf…