Spring 依赖 详解
Spring 依赖详解
在 Spring 框架中,依赖 是指一个对象(Bean)需要另一个对象(Bean)来完成其功能的情况。Spring 通过 依赖注入(Dependency Injection, DI) 和 控制反转(Inversion of Control, IoC) 来实现对依赖的管理。
1. 什么是依赖?
1.1 概念
- 依赖 是指一个类需要另一个类的协助才能完成其工作。
- 例如,
OrderService可能依赖于OrderRepository来访问数据库。
1.2 传统方式的问题
- 在传统开发中,依赖通过手动创建实例(
new)来实现。 - 问题:
- 强耦合:代码依赖具体实现,难以扩展和替换。
- 难以测试:无法轻松替换依赖的 Mock 对象。
- 复杂管理:在大型项目中,依赖关系复杂且难以维护。
2. Spring 依赖的管理
Spring 使用 IoC 容器来管理依赖,通过 依赖注入 将依赖关系注入到对象中,解决传统方式的问题。
2.1 依赖注入(DI)的核心思想
- 对象本身不负责管理其依赖的创建,而是由外部容器注入。
- 依赖关系在配置文件(XML、JavaConfig)或注解中声明。
3. 依赖注入的方式
Spring 提供三种主要的依赖注入方式:
3.1 构造器注入
- 概念:通过构造方法注入依赖。
- 优点:
- 强制依赖注入,避免遗漏。
- 有助于实现不可变对象。
- 示例:
@Component public class OrderService {private final OrderRepository orderRepository;@Autowiredpublic OrderService(OrderRepository orderRepository) {this.orderRepository = orderRepository;} }
3.2 Setter 方法注入
- 概念:通过 Setter 方法注入依赖。
- 优点:
- 灵活性高,可以在运行时动态替换依赖。
- 适用于可选依赖。
- 示例:
@Component public class OrderService {private OrderRepository orderRepository;@Autowiredpublic void setOrderRepository(OrderRepository orderRepository) {this.orderRepository = orderRepository;} }
3.3 字段注入
- 概念:直接在字段上注入依赖。
- 优点:
- 代码简洁,省略了 Getter 和 Setter。
- 缺点:
- 不支持依赖的不可变性。
- 不便于单元测试。
- 示例:
@Component public class OrderService {@Autowiredprivate OrderRepository orderRepository; }
4. 依赖的配置方式
Spring 提供以下几种方式配置依赖关系:
4.1 基于注解的配置(推荐)
- 使用注解标记类和依赖关系。
- 主要注解:
@Component:声明一个类是 Spring 容器中的 Bean。@Autowired:自动注入依赖。@Qualifier:指定具体的 Bean。@Primary:优先注入特定 Bean。
- 示例:
@Component public class OrderRepository {}@Component public class OrderService {@Autowiredprivate OrderRepository orderRepository; }
4.2 基于 XML 的配置
- 在 XML 文件中定义 Bean 和依赖关系。
- 示例:
<beans><bean id="orderRepository" class="com.example.OrderRepository"/><bean id="orderService" class="com.example.OrderService"><property name="orderRepository" ref="orderRepository"/></bean> </beans>
4.3 基于 JavaConfig 的配置
- 使用 Java 类和注解定义 Bean 和依赖关系。
- 示例:
@Configuration public class AppConfig {@Beanpublic OrderRepository orderRepository() {return new OrderRepository();}@Beanpublic OrderService orderService(OrderRepository orderRepository) {return new OrderService(orderRepository);} }
5. 自动装配(Autowired)
5.1 @Autowired 的工作原理
- Spring 通过类型匹配自动注入依赖。
- 可以与
@Qualifier或@Primary配合使用,以解决多个候选 Bean 的问题。
5.2 示例
@Component
public class OrderService {@Autowiredprivate OrderRepository orderRepository;
}
6. 多 Bean 配置与冲突解决
当存在多个类型相同的 Bean 时,Spring 提供以下解决方案:
6.1 使用 @Qualifier
- 明确指定注入的 Bean。
- 示例:
@Component("repo1") public class OrderRepository {}@Component("repo2") public class BackupRepository {}@Component public class OrderService {@Autowired@Qualifier("repo1")private OrderRepository orderRepository; }
6.2 使用 @Primary
- 设置默认的优先级 Bean。
- 示例:
@Component @Primary public class OrderRepository {}
7. 作用域(Scope)
Spring 中 Bean 的默认作用域是 单例(Singleton),还支持其他作用域:
- Singleton:整个应用中仅有一个实例(默认)。
- Prototype:每次获取时创建新的实例。
- Request:每个 HTTP 请求一个实例(Web 应用)。
- Session:每个 HTTP 会话一个实例(Web 应用)。
- Application:每个 ServletContext 一个实例(Web 应用)。
示例
@Component
@Scope("prototype")
public class OrderService {}
8. 循环依赖
8.1 什么是循环依赖?
- 两个或多个 Bean 互相依赖,形成循环。
- 示例:
@Component public class A {@Autowiredprivate B b; }@Component public class B {@Autowiredprivate A a; }
8.2 Spring 的解决方式
- 单例模式:
- Spring 使用三级缓存解决循环依赖:
- 一级缓存:完整实例(单例池)。
- 二级缓存:半成品实例。
- 三级缓存:对象工厂,用于创建代理对象。
- Spring 使用三级缓存解决循环依赖:
- 原型模式:
- 不支持循环依赖,抛出异常。
8.3 避免循环依赖的建议
- 重构代码,避免互相注入。
- 使用
@Lazy注解延迟加载。 - 使用构造器注入时确保无循环依赖。
9. 依赖的生命周期
Spring Bean 的生命周期由容器管理,主要包括以下阶段:
- 实例化:通过反射创建对象。
- 依赖注入:注入依赖对象。
- 初始化:执行初始化方法。
- 使用:Bean 被调用。
- 销毁:容器关闭时调用销毁方法。
示例
@Component
public class OrderService {@PostConstructpublic void init() {System.out.println("Initializing OrderService");}@PreDestroypublic void destroy() {System.out.println("Destroying OrderService");}
}
10. Spring 依赖的优缺点
10.1 优点
- 降低耦合:Bean 的创建和管理由容器负责,模块更加独立。
- 便于测试:可以轻松替换依赖为 Mock 对象。
- 增强灵活性:可以动态配置和替换 Bean。
- 代码简洁:减少手动管理依赖的代码。
10.2 缺点
- 学习曲线:需要理解 IoC 和 DI 的概念及实现。
- 配置复杂性:在大型项目中,Bean 和依赖关系可能变得复杂。
- 性能开销:动态代理和反射可能会影响性能。
11. 总结
Spring 的依赖管理通过 IoC 容器和依赖注入,大幅提升了代码的灵活性、可读性和可维护性。通过多种注入方式(构造器、Setter、字段),以及配置方式(注解、XML、JavaConfig),Spring 适应了
各种开发场景。深入理解 Spring 依赖的机制和原理,有助于开发者设计更优雅、解耦的系统架构。
相关文章:
Spring 依赖 详解
Spring 依赖详解 在 Spring 框架中,依赖 是指一个对象(Bean)需要另一个对象(Bean)来完成其功能的情况。Spring 通过 依赖注入(Dependency Injection, DI) 和 控制反转(Inversion of…...
千益畅行,旅游卡有些什么优势?
千益畅行共享旅游卡是一种创新的旅游服务模式,旨在通过整合各类旅游资源,为用户提供一站式的旅游解决方案。这张旅游卡支持2至6人同行,涵盖了接机、酒店、用餐、大巴、导游、景区门票等服务,用户只需自行承担往返交通费用即可享受…...
Ubuntu24 cgroupv2导致rancher(k3s)启动失败的处理
方案一: 修改系统镜像为ubuntu18 方案二: 修改当前系统的cgroup版本,由v2改成v1 修改步骤: 1、查看当前cgroup版本 stat -fc %T /sys/fs/cgroup cgroup v2,输出结果为cgroup2fs cgroup v1,输出为tm…...
学习CSS第二天
学习文章目录 一.内部样式 一.内部样式 写在 html 页面内部,将所有的 CSS 代码提取出来,单独放在 <style> 标签中 语法: <style> h1 { color: red; font-size: 40px; } </style>注意点: <style> 标签理…...
2021数学分析【南昌大学】
2021 数学分析 求极限 lim n → ∞ 1 n ( n + 1 ) ( n + 2 ) ⋯ ( n + n ) n \lim_{n \to \infty} \frac{1}{n} \sqrt [n]{(n+1)(n+2) \cdots (n+n)} n→∞limn1n(n+1)(n+2)⋯(n+n) lim n → ∞ 1 n ( n + 1 ) ( n + 2 ) ⋯ ( n + n ) n = lim n → ∞ ( n + …...
单端和差分信号的接线法
内容来源:【单端信号 差分信号与数据采集卡的【RSE】【 NRES】【 DIFF】 模式的连接】 此篇文章仅作笔记分享。 单端输入 单端信号指的是输入信号由一个参考端和一个信号端构成,参考端一般是地端,信号就是通过计算信号端口和地端的差值所得…...
力扣-图论-2【算法学习day.52】
前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向和记录学习过程(例如想要掌握基础用法,该刷哪些题?)我的解析也不会做的非常详细,只会提供思路和一些关键点,力扣上的大佬们的题解质量是非…...
MySQL如何区分幻读和不可重复读
在MySQL中,幻读和不可重复读都是并发事务中可能出现的问题,但它们的表现和原因略有不同。 不可重复读 (Non-Repeatable Read) 不可重复读是指在同一个事务内,多次读取同一行数据时,可能会得到不同的结果。这种情况发生在一个事务…...
界面控件Syncfusion Essential Studio®现在已完全支持 .NET 9
Syncfusion Essential Studio现在完全支持 .NET 9,可最新版本2024 Volume 3 版本中使用!通过此更新,Blazor、.NET MAUI、WPF、WinForms、WinUI和ASP.NET Core 平台中的 Syncfusion 组件以及文档处理库已准备好让您利用 .NET 9 中的最新功能。…...
openEuler安装lsb_release
lsb_release是linux下查看发行版信息用的工具 lsb_release只是一个小程序,它的包名并不是lsb_release lsb_release其实是红帽的一个项目,其名为redhat-lsb 我们的lsb_release就是其中的一部分,更准确的说是redhat-lsb-core 从网站࿱…...
统计数字字符个数
统计数字字符个数 C语言实现C实现Java实现Python实现 💐The Begin💐点点关注,收藏不迷路💐 输入一行字符,统计出其中数字字符的个数。 输入 一行字符串,总长度不超过255。 输出 出为1行,输出…...
44页PDF | 信息化战略规划标准框架方法论与实施方法(限免下载)
一、前言 这份报告详细介绍了企业信息化战略规划的标准框架、方法论以及实施方法,强调了信息化规划应以业务战略和IT战略为驱动力,通过构筑企业架构(EA)来连接长期战略和信息化建设。报告提出了信息化规划原则,探讨了…...
计算机网络期末复习-part1-概述
1、互联网的组成 互联网由两大块组成。 1、边沿部分:由所有连接在互联网上的主机组成,是用户直接使用的部分。 2、核心部分,由大量网络和路由器组成,为边缘部分提供服务。 2、数据传送阶段的三种交换方式的主要特点 1、电路交…...
A1228 php+Mysql旅游供需平台的设计与实现 导游接单 旅游订单 旅游分享网站 thinkphp框架 源码 配置 文档 全套资料
旅游供需平台 1.项目描述2. 开发背景与意义3.项目功能4.界面展示5.源码获取 1.项目描述 随着社会经济的快速发展,生活水平的提高,人们对旅游的需求日益增强,因此,为给用户提供一个便利的查看导游信息,进行导游招募的平…...
RabbitMQ消息可靠性保证机制5--消息幂等性处理
RabbitMQ层面有实现“去重机制”来保证“恰好一次”吗?答案是没并没有,而且现在主流的消息中间件都没有实现。 一般解决重复消息的办法是:在消费端让我们消费消息操作具有幂等性。 幂等性问题并不是消息系统独有,而是࿰…...
Claude3.5如何使用?
Claude 3.5 Sonnet,性能直接吊打了 GPT-4o,甚至价格还更便宜。网友们纷纷展开实测,有人表示自己一半的工作已经可以由它替代了!而最让人惊喜的新功能,莫过于 Artifacts 了。 就在昨天,Anthropic 深夜发布了…...
力扣刷题TOP101:14.BM16 删除有序链表中重复的元素-II
目录: 目的 思路 复杂度 记忆秘诀 python代码 目的 1→1→2→3→3 删除重复后变成2。 思路 这个任务是删除链表里重复的节点包含本身。可以看成是一个抽奖活动的系统升级。某人通过多种方式报名(节点不同),后台数据检测到这些…...
解决github网络慢的问题
前言 本文采用替换host的方式来加速github的git请求,主要我自己用来备份的懒人方式,不然每次都要手动修改hosts文件,skrskrskr… 一、获取到可用的ip 先到这个网站查询到低延迟的ip 站长工具:https://ping.chinaz.com/ 第2步&…...
docker及docker exec命令学习笔记
docker exec 是一个常用的 Docker 命令,允许你在已经运行的容器中执行命令或启动新的进程。以下是详细介绍和常见用法: 基本语法 docker exec [OPTIONS] CONTAINER COMMAND [ARG...]参数详解 1. CONTAINER指定目标容器的名字或容器 ID。可以通过以下命…...
linux环境宝塔服务部署安装及介绍
一、简介 宝塔面板是一款服务器管理软件,支持windows和linux系统,可以通过Web端轻松管理服务器,提升运维效率。例如:创建管理网站、FTP、数据库,拥有可视化文件管理器,可视化软件管理器,可视化C…...
Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...
DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径
目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
iPhone密码忘记了办?iPhoneUnlocker,iPhone解锁工具Aiseesoft iPhone Unlocker 高级注册版分享
平时用 iPhone 的时候,难免会碰到解锁的麻烦事。比如密码忘了、人脸识别 / 指纹识别突然不灵,或者买了二手 iPhone 却被原来的 iCloud 账号锁住,这时候就需要靠谱的解锁工具来帮忙了。Aiseesoft iPhone Unlocker 就是专门解决这些问题的软件&…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
优选算法第十二讲:队列 + 宽搜 优先级队列
优选算法第十二讲:队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...
技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...
