当前位置: 首页 > news >正文

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

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 类
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. 依赖注入到其他类
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. 字段注入
@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 注入
@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 的实现类:

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:

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。

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 的冲突问题。

相关文章:

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

Spring Boot 中的依赖注入(Dependency Injection,简称 DI)是通过 Spring 框架的核心机制——控制反转(Inversion of Control,IOC)容器来实现的。Spring Boot 基于 Spring Framework,在应用中自动…...

ubuntu22.04 编译安装libvirt 10.x

环境安装 sudo apt-get update -y sudo apt-get install qemu-system-x86 bridge-utils libyajl-dev -y sudo apt-get install build-essential autoconf automake libtool -y sudo apt-get install libxml2-dev libxslt1-dev libgnutls28-dev libpciaccess-dev libnl-3-de…...

[fastadmin] 第三十四篇 FastAdmin 商城模块标签使用详解

FastAdmin 商城模块标签使用详解 一、标签基本语法 1.1 基础语法格式 {shop:goodslist flag"参数值" id"变量名" row"数量"}<!-- 循环内容 --> {/shop:goodslist}1.2 常用参数说明 flag: 商品标记筛选id: 循环变量名row: 显示数量 1.…...

(2024,LLaVA-Bench (Wilder),LLaVA-NeXT,LLaMA3,Qwen-1.5,语言模型扩展)

LLaVA-NeXT: Stronger LLMs Supercharge Multimodal Capabilities in the Wild 目录 1. 简介 2. 探索大规模语言模型的能力极限 3. LLaVA-Bench (Wilder)&#xff1a;日常生活视觉聊天基准 4. Benchmark 结果 1. 简介 我们通过引入近期更强大的开源大语言模型&#xff08;…...

IPEX-LLM开发项目过程中的技术总结和心得

IPEX-LLM开发项目过程中的技术总结和心得 在人工智能快速发展的时代&#xff0c;高效地开发和部署大语言模型&#xff08;LLM&#xff09;已成为技术人员的必备技能。在我们的项目中&#xff0c;我们采用了 Intel Extension for PyTorch&#xff08;简称 IPEX&#xff09;和 L…...

HTTP/HTTPS ②-Cookie || Session || HTTP报头

这里是Themberfue 上篇文章介绍了HTTP报头的首行信息 本篇我们将更进一步讲解HTTP报头键值对的含义~~~ ❤️❤️❤️❤️ 报头Header ✨再上一篇的学习中&#xff0c;我们了解了HTTP的报头主要是通过键值对的结构存储和表达信息的&#xff1b;我们已经了解了首行的HTTP方法和UR…...

【软考】软件设计师

「学习路线」&#xff08;推荐该顺序学习&#xff0c;按照先易后难排序&#xff09; 1、上午题—计算机系统&#xff08;5~6分&#xff09;[1.8; ] 2、上午题—程序设计语言&#xff08;固定6分&#xff09;[1.9; ] 3、下午题—试题一&#xff08;15分&#xff09; 4、上午题—…...

K8s Pod OOMKilled,监控却显示内存资源并未打满

1. 问题现象 pod一直重启&#xff0c;通过grafana查看&#xff0c;发现内存使用率并没有100%。 2. 排查过程 2.1 describe查看pod最新一次的状态 可以明显看到&#xff0c;最近一次的重启就是因为内存不足导致的。 2.2 describe 查看node节点状态 找到原因了&#xff0c;原来…...

C++ 原子变量

C 原子变量 文章目录 C 原子变量1. 原子变量是什么&#xff1f;2. 原子操作的特点3. 原子变量的作用1. 多线程安全的共享数据访问2. 替代锁机制3. 实现低级同步算法 4. 原子变量的常见操作5. 内存顺序&#xff08;Memory Ordering&#xff09;内存顺序控制在原子变量中的作用如…...

linux网络 | http结尾、理解长连接短链接与cookie

前言&#xff1a;本节是http章节的最后一部分&#xff0c;主要解释一些小概念。讲解到了HTTP的方法&#xff0c;表单&#xff0c; 重定向等等。 现在废话不多说&#xff0c; 开始我们的学习吧。 ps&#xff1a;本节内容都是概念&#xff0c; 知道就行&#xff0c; 友友们放心观…...

金融项目实战 02|接口测试分析、设计以及实现

目录 ⼀、接口相关理论 二、接口测试 1、待测接口&#xff1a;投资业务 2、接口测试流程 3、设计用例理论 1️⃣设计方法 2️⃣工具 4、测试点提取 5、测试用例 ⼀、接口相关理论 1、ui功能测试和接⼝测试那个先执⾏&#xff1f;为什么&#xff1f; 结论&#xff1a…...

二、智能体强化学习——深度强化学习核心算法

2.1 DQN 系列及其改进 2.1.1 背景与动机 在经典强化学习中&#xff08;如 Q-Learning&#xff09;&#xff0c;如果状态空间或动作空间非常大乃至连续&#xff0c;那么用一个表格来存储 Q ( s , a ) Q(s,a) Q(s,a) 不再可行。为了解决该问题&#xff0c;可以使用神经网络来逼…...

Mysql--架构篇--存储引擎InnoDB(内存结构,磁盘结构,存储结构,日志管理,锁机制,事务并发控制等)

MySQL是一个多存储引擎的数据库管理系统&#xff0c;支持多种不同的存储引擎。每种存储引擎都有其独特的特性、优势和适用场景。选择合适的存储引擎对于优化数据库性能、确保数据完整性和满足业务需求至关重要。 注&#xff1a;在同一个Mysql的数据库中&#xff0c;对于不同的表…...

JVM实战—13.OOM的生产案例

大纲 1.每秒仅上百请求的系统为何会OOM(RPC超时时间设置过长导致QPS翻几倍) 2.Jetty服务器的NIO机制如何导致堆外内存溢出(S区太小 禁NIO的显式GC) 3.一次微服务架构下的RPC调用引发的OOM故障排查实践(MAT案例) 4.一次没有WHERE条件的SQL语句引发的OOM问题排查实践(使用MA…...

client-go 的 QPS 和 Burst 限速

1. 什么是 QPS 和 Burst &#xff1f; 在 kubernetes client-go 中&#xff0c;QPS 和 Burst 是用于控制客户端与 Kubernetes API 交互速率的两个关键参数&#xff1a; QPS (Queries Per Second) 定义&#xff1a;表示每秒允许发送的请求数量&#xff0c;即限速器的平滑速率…...

使用docker-compose安装Redis的主从+哨兵模式

必看 本文是一主二从一哨兵模式&#xff1b;其余的单机/集群/多哨兵模式的话&#xff0c;不在本文... 本文的环境主要是&#xff1a;应用app在本地&#xff0c;redis在云服务器上&#xff1b; 图解 图如下&#xff1a;这个图很重要&#xff1b; 之所以要这样画图&#xff0…...

数据结构(Java版)第七期:LinkedList与链表(二)

专栏&#xff1a;数据结构(Java版) 个人主页&#xff1a;手握风云 一、链表的实现&#xff08;补&#xff09; 接上一期&#xff0c;下面我们要实现删除所有值为key的元素&#xff0c;这时候有的老铁就会想用我们上一期中讲到的remove方法&#xff0c;循环使用remove方法&#…...

ant-design-vue 1.X 通过id获取a-input组件失败

1.ant-design-vue 1.X 问题描述 当我在a-form组件中&#xff0c;以v-decorator指令绑定表单组件时&#xff0c;无法根据我设置的verify-code-input获取元素 <a-input type"text" id"verify-code-input" class"paIpt":placeholder"$t(…...

Flutter:吸顶效果

在分页中&#xff0c;实现tab吸顶。 TDNavBar的screenAdaptation: true, 开启屏幕适配。 该属性已自动对不同手机状态栏高度进行适配。我们只需关注如何实现吸顶。 view import package:ducafe_ui_core/ducafe_ui_core.dart; import package:flutter/material.dart; import p…...

MATLAB语言的数据类型

MATLAB语言的数据类型详解 MATLAB&#xff08;矩阵实验室&#xff09;是一种广泛应用于科学计算、数据分析、算法开发及模型构建的高性能语言和环境。MATLAB的强大之处不仅在于其丰富的数学工具和可视化功能&#xff0c;还有其灵活多变的数据类型。这篇文章将详细介绍MATLAB中…...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

云启出海,智联未来|阿里云网络「企业出海」系列客户沙龙上海站圆满落地

借阿里云中企出海大会的东风&#xff0c;以**「云启出海&#xff0c;智联未来&#xff5c;打造安全可靠的出海云网络引擎」为主题的阿里云企业出海客户沙龙云网络&安全专场于5.28日下午在上海顺利举办&#xff0c;现场吸引了来自携程、小红书、米哈游、哔哩哔哩、波克城市、…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

多模态商品数据接口:融合图像、语音与文字的下一代商品详情体验

一、多模态商品数据接口的技术架构 &#xff08;一&#xff09;多模态数据融合引擎 跨模态语义对齐 通过Transformer架构实现图像、语音、文字的语义关联。例如&#xff0c;当用户上传一张“蓝色连衣裙”的图片时&#xff0c;接口可自动提取图像中的颜色&#xff08;RGB值&…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)

Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败&#xff0c;具体原因是客户端发送了密码认证请求&#xff0c;但Redis服务器未设置密码 1.为Redis设置密码&#xff08;匹配客户端配置&#xff09; 步骤&#xff1a; 1&#xff09;.修…...