登录
/
注册
首页
论坛
其它
首页
科技
业界
安全
程序
广播
Follow
关于
导读
排行榜
资讯
发帖说明
登录
/
注册
账号
自动登录
找回密码
密码
登录
立即注册
搜索
搜索
关闭
CSDN热搜
程序园
精品问答
技术交流
资源下载
本版
帖子
用户
软件
问答
教程
代码
写记录
写博客
小组
VIP申请
VIP网盘
网盘
联系我们
发帖说明
道具
勋章
任务
淘帖
动态
分享
留言板
导读
设置
我的收藏
退出
腾讯QQ
微信登录
返回列表
首页
›
业界区
›
业界
›
依赖注入(DI)与控制反转(IoC)
依赖注入(DI)与控制反转(IoC)
[ 复制链接 ]
寅斫
2025-6-3 14:51:16
程序园永久vip申请,500美金$,无限下载程序园所有程序/软件/数据/等
导航
1前言
2什么是依赖注入与控制反转
2.1控制反转
2.2依赖注入
3为什么要使用依赖注入与控制反转
3.1解耦
3.2单元测试
4IoC容器
5结束语
1 前言
依赖注入(DI)与控制反转(IoC)可能是一些开发小伙伴耳熟但又不能详的两个词,经常看到它们的名字,但又不理解。这两个词来源于英文直译,看似高深莫测,其实非常简单,并且在一些开发场景中扮演着不可或缺的角色,比如单元测试离不开依赖注入,IoC容器是插件框架的最佳拍档等,本文尝试以最简单的方式阐述这两种思想在开发中的应用。文章来源:https://www.wubayue.com
2 什么是依赖注入与控制反转
2.1 控制反转
在解释控制反转前,首先需要理解什么是“正转”:A依赖于B,并且A掌控B的创建销毁,此时A控制了B,即为“正转”。
当B的创建销毁在A之外完成,B脱离了A的控制,称之为控制反转(IoC:Invertion of Control)。
public class A
{
private B _b;
public A()
{
// 因为A掌控B的创建,因此A控制了B,此为“正转”
_b = new B();
}
}
复制代码
2.2 依赖注入
对象之间的依赖不再由内部创建,而是由外部传递,称之为依赖注入(DI:Dependency Injection)。
控制反转是设计思想,依赖注入是实现手段。两者缺一不可:
public class A
{
private B _b;
// B由外部注入,称之为依赖注入
public A(B b)
{
// B由外部创建,脱离了A的控制,称之为控制反转
_b = b;
}
}
复制代码
如上代码示例的是构造函数注入,另一种常见的依赖注入方式是属性注入:
public class A
{
public B B { get; set; }
}
void main()
{
A a = new A();
B b = new B();
// 属性注入
a.B = b;
}
复制代码
3 为什么要使用依赖注入与控制反转
3.1 解耦
在软件行业,有一条黄金法则叫“高内聚,低耦合”。耦合表示使用(或称为依赖),比如B使用了A,即B耦合了A,只要类的数量一多,类之间千丝万缕的耦合关系会成为巨大挑战,高内聚就是把相同的功能放在一起,这样类之间的耦合关系就会减少,通过提升内聚来减少类之间的耦合是一种常见的解耦方式。如上图,C依赖B,B依赖A,原本是两级依赖关系,通过将B中的部分功能向A内聚(前提是这部分功能原本就具有相关性),实现了B、C都依赖于A的一级依赖关系,B、C之间完成了解耦。
解耦除了完全消除依赖关系以外,另一种方式是将紧耦合转换为松耦合。先解释一下松紧耦合的概念,我们打开电脑机箱找到主机板上的南北桥芯片,可以看到它们是完全焊接在主板上的,这种不可替换的连接即为紧耦合;再找到内存条,发现它们可以拆卸并更换为其它品牌,这种可替换的连接即为松耦合。大部分时候,在软件设计开发时都应使用松散耦合,而依赖注入就是实现松散耦合非常好的一种方式。
如果我们再稍思考一下,主板上的内存条为什么能安装不同的品牌?原因是有相关技术标准,比如长宽尺寸,针脚数量,通信标准等,不同的内存条厂商,只要遵循标准生产出来的内存条就能安装到同一块主板上。在软件开发中,让主板支持不同厂商的内存条称之为可扩展性,定义内存条接口标准称之为抽象,根据标准生产内存条称之为面向抽象编程(或面向接口编程)。因此为了使软件模块具备更好的扩展性,除了使用依赖注入,还应注入抽象而非具体。
3.2 单元测试
不了解单元测试的小伙伴可先阅读我的另一篇文章《单元测试从入门到精通》。在单元测试中如果没有依赖注入,几乎寸步难行,通过简单的代码来示例:
难以测试的代码:
// 被测对象
public class House
{
private Bedroom _bedroom;
House()
{
// 内部构造协作对象,难以被测试。
_bedroom = new Bedroom();
}
// ...
}
// 测试用例
public void TestThisIsReallyHard()
{
House house = new House();
// 无法在测试过程中对Bedroom进行属性赋值、行为方法调用等,测试寸步难行
// ...
}
复制代码
易于测试的代码:
// 被测对象
public class House
{
private Bedroom _bedroom;
// 注入协作对象,可测试性好。
House(Bedroom b)
{
_bedroom = b;
}
// ...
}
// 测试用例
public void TestThisIsEasyAndFlexible()
{
// Bedroom对象在掌控之中,易于测试
Bedroom bedroom = new Bedroom();
House house = new House(bedroom);
// ...
}
复制代码
4 Ioc容器
在稍复杂的软件产品中,通常会遇到两个关于对象的问题:一是对象的数量众多,如何统一对它们进行管理,比如统一管理对象的创建销毁过程,每个对象的生命周期;二是对象之间可能存在多重复杂的依赖关系,如何对这些依赖关系进行管理,比如谁先创建谁后创建,被依赖的对象如何注入依赖对象等。
针对如上两个问题的解决方案就是IoC容器(IoC Container),IoC容器是一个对象管理器,它统一管理对象的创建销毁过程、生命周期、依赖关系,以及提供自动注入、根据配置创建对象等一系列便捷功能。如下代码使用 Autofac(C#开源IoC容器)进行了简单示例:
// 使用开源IoC容器Autofac
using Autofac;
namespace AutofacDemo
{
class A
{ }
class B
{
A _a;
// 只需要声明需要注入的对象,由容器自动完成依赖对象的创建与注入
public B(A a)
{
_a = a;
}
}
internal class Program
{
static void Main(string[] args)
{
// 将类型注册至容器中
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType();
// 设置对象的生命周期(单例模式)
builder.RegisterType<B>().SingleInstance();
// 构造IoC容器
IContainer container = builder.Build();
// 从容器中获取对象
B b = container.Resolve<B>();
}
}
}
复制代码
5 结束语
依赖注入与控制反转的思想诞生于软件开发追求高内聚、低耦合的历史进程中,20世纪90年代末已在软件设计模式、单元测试中使用。2002年Java的Spring框架搭载IoC容器、AOP等大杀器风靡全球,DI与IoC被更多的开发者关注。直到最近的项目中涉及插件化框架,而IoC容器又是插件架构的最佳拍档,因此将其整理成文。如能给人予帮助,不甚荣幸。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
依赖
注入
DI
控制
反转
相关帖子
ImageViewer.js:一个零依赖的现代化图片预览组件
fix-broken-img:零依赖的图片优雅降级解决方案
强的飞起的 Roslyn 编译时代码生成,实现抽象类继承与依赖注入的自动化配置
安装odoo18依赖报错command 'x86_64-linux-gnu-gcc'
具身智能:零基础入门睿尔曼机械臂(三)——夹爪抓取与释放控制全解析
串联控制环路仿真解析
Python 程序的流程控制
咱们聊聊Spring循环依赖那点事儿:从“死锁”到“三级缓存”的奇妙之旅
Python新利器:用uv轻松管理venv虚拟环境和pip依赖包
回复
使用道具
举报
提升卡
置顶卡
沉默卡
喧嚣卡
变色卡
千斤顶
照妖镜
相关推荐
业界
ImageViewer.js:一个零依赖的现代化图片预览组件
3
456
笙芝
2025-11-22
业界
fix-broken-img:零依赖的图片优雅降级解决方案
0
303
乃阕饯
2025-11-30
业界
强的飞起的 Roslyn 编译时代码生成,实现抽象类继承与依赖注入的自动化配置
1
501
忿媚饱
2025-12-03
安全
安装odoo18依赖报错command 'x86_64-linux-gnu-gcc'
1
842
涣爹卮
2025-12-03
安全
具身智能:零基础入门睿尔曼机械臂(三)——夹爪抓取与释放控制全解析
2
309
乱蚣
2025-12-10
业界
串联控制环路仿真解析
1
64
乐敬
2025-12-11
安全
Python 程序的流程控制
1
945
明思义
2025-12-11
业界
咱们聊聊Spring循环依赖那点事儿:从“死锁”到“三级缓存”的奇妙之旅
1
713
赏听然
2025-12-14
业界
Python新利器:用uv轻松管理venv虚拟环境和pip依赖包
0
799
敖可
2025-12-16
回复
(2)
里豳朝
2025-10-21 22:25:41
回复
使用道具
举报
照妖镜
程序园永久vip申请,500美金$,无限下载程序园所有程序/软件/数据/等
前排留名,哈哈哈
矛赓宁
2025-12-10 09:40:30
回复
使用道具
举报
照妖镜
程序园永久vip申请,500美金$,无限下载程序园所有程序/软件/数据/等
过来提前占个楼
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
|
立即注册
回复
本版积分规则
回帖并转播
回帖后跳转到最后一页
浏览过的版块
安全
签约作者
程序园优秀签约作者
发帖
寅斫
2025-12-10 09:40:30
关注
0
粉丝关注
14
主题发布
板块介绍填写区域,请于后台编辑
财富榜{圆}
3934307807
991124
anyue1937
9994891
kk14977
6845357
4
xiangqian
638210
5
韶又彤
9997
6
宋子
9982
7
闰咄阅
9993
8
刎唇
9993
9
俞瑛瑶
9998
10
蓬森莉
9951
查看更多
今日好文热榜
599
alist如何将默认布局设置为图片布局
1007
Kali2025.4+Cherry Studio一键配置HexStrik
417
PHP 之高级面向对象编程 深入理解设计模式
414
PHP 之高级面向对象编程 深入理解设计模式
570
升级curl版本,及升级后引起的动态库链接不
294
2025年GEO优化服务商全景对比:五大核心维
779
AI Agent详解
983
Buildah 简明教程:让镜像构建更轻量,告别
610
OceanBase 在滴滴大规模运维经验以及新功能
975
[CSS+]HTML Learn Data Day 2
96
掌握相关性分析:读懂数据间的“悄悄话”
138
嵌入式UI框架-抗锯齿画圆弧算法
935
嵌入式UI框架的渐变原理、渐变算法
220
日本股票 API 对接实战指南(实时行情与 IP
562
解决Docker磁盘空间告急:认识并清理“悬空
394
别再只会算直线距离了!用“马氏距离”揪出
530
企业进行信息化后,一定会提高效率吗?真相
516
n8n整合ffmpeg
492
从random随机数看验证码重复数字
525
OceanBase 向量索引优化指南