剖析DI
0x00.前言
当我们研究一些晦涩的源码,上网查阅资料的时候,映入眼帘的总有这么些名词:DIP、IOC、DI、DL、IOC容器这些专业名词。如果不懂这些名词背后的含义,我们内心有可能是这样的:

0x01.小例子
/**
* 餐厅类
*/
public class Restaurant {
//后台收银系统
private WeChatPay pay = new WeChatPay();
//收款操作
public void transact(double money) {
pay.receiveMoney(money);
}
}
import java.util.Date;
/**
* 微信
*/
public class WeChatPay {
public void receiveMoney(double money) {
System.out.println(new Date() + ",已用微信收款:" + money + "元");
}
}

这时候Restaurant类就依赖于WeChatPay,两个类产生依赖
0x02.DIP
DIP的英文名:Dependency Inversion Principle,中文名:依赖倒转原则
定义:
High-level modules should not depend on low-level modules. Both should depend on abstractions
Abstractions should not depend on details. Details should depend on abstractions
理解:
高层模块不应该直接依赖于底层模块的具体实现,而应该依赖于底层的抽象。换言之,模块间的依赖是通过抽象发生,实现类之间的不发生直接依赖关系,其依赖关系是通过接口或抽象类产生的
面向接口编程
它仅仅是面向对象软件设计的一种原则。它仅仅告诉你两个模块之间如何协调依赖关系,但是并没有告诉你如何做!
举个例子
我们经常所说的三层架构(UI、BLL、DAL)


图二的版本,就是高层模块依赖于低层模块的抽象,就好像依赖“倒置”。这样可以使得整体的架构更加的稳定,灵活,及自如的面对需求的变化。
0x03.IOC
- IOC的英文名:Inversion Of Control ,中文名:控制反转
- IOC基于DIP原则上的实现的是一种软件设计模式,它告诉你应该如何做,来解除相互依赖模块的耦合。它为相互依赖的组件提供抽象,将依赖对象的获得交给第三方来控制,即依赖对象不在被依赖的类中直接通过new来获取。
- IOC的实现的方式一般有两种,依赖注入和依赖查找。一般DI使用的比较多
0x04.DI
- DI的英文名:Dependency Injection,中文名称:依赖注入。
- DI就是将依赖对象的创建和绑定转移到被依赖对象类的外部来实现。它提供是一种机制,将需要依赖(低层模块)对象的引用传递给被依赖(高层模块)对象。
DI注入有三种方式:
- 构造函数注入
- 属性注入
- 接口注入
Demo讲解
/**
* di Ipay 接口
*/
public interface IPay {
void receiveMoney(double money);
}
/**
* 重构后的微信支付
*/
public class WebChatPay implements IPay {
public void receiveMoney(double money) {
Date now = new Date();
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println(format.format(now) + ",已用重构后的微信收款:" + money + "元");
}
}
/**
* 重构后的餐厅类构造器注入
*/
public class Restaurant {
private IPay _pay;
public Restaurant(IPay pay) {
this._pay = pay;
}
//收款操作
public void transact(double money) {
_pay.receiveMoney(money);
}
}
0x01.构造器注入
System.out.println("==========通过构造函数注入开始==============");
IPay pay = new WebChatPay();//在外部创建依赖对象
Restaurant restaurant = new Restaurant(pay);
restaurant.transact(10);
System.out.println("==========通过构造函数注入结束==============");

这时候我们就看到Restaurant将依赖的WeChatPay对象的创建和绑定转移到Restaurant类外部来实现了。这样就解除了Restaurant类与WeChatPay类的耦合关系。如果将支付方式改成Alipay,只需要定义一个Alipay类,然后在外部重新绑定依赖。不需要修改Restaurant类。
0x02.属性注入
System.out.println("==========通过属性注入开始==============");
IPay paySetter = new WebChatPay();
RestaurantBySetter restaurantSetter = new RestaurantBySetter();
restaurantSetter.setPay(paySetter);
restaurantSetter.transact(10);
System.out.println("==========通过属性注入结束==============");

0x03.接口注入
System.out.println("==========通过接口注入开始==============");
IPay payInterface = new WebChatPay();
RestaurantByInterface restaurantInterface = new RestaurantByInterface();
restaurantInterface.extraInstance(payInterface);
restaurantInterface.transact(10);
System.out.println("==========通过接口注入结束==============");

0x05.IOC容器
DI框架,用来自动创建、维护依赖对象,并管理其生命周期。
常使用的IOC容器有:
Net:Ninject、Spring.NET、Unity、Autofac等
Java:Spring等
0x06.总结
IOC带来好处:
- 降低了各个组件之间的耦合性,增强了内聚性。
- 大中型项目,团队分工明确,职责明确,便于测试
- 使得模块具有热插拔特性,增加了模块的复用性
剖析DI的更多相关文章
- ASP.NET MVC不可或缺的部分——DI(IOC)容器及控制器重构的剖析(DI的实现原理)
IoC框架最本质的东西:反射或者EMIT来实例化对象.然后我们可以加上缓存,或者一些策略来控制对象的生命周期,比如是否是单例对象还是每次都生成一个新的对象. DI实现其实很简单,首先设计类来实现接口, ...
- 从EFCore上下文的使用到深入剖析DI的生命周期最后实现自动属性注入
故事背景 最近在把自己的一个老项目从Framework迁移到.Net Core 3.0,数据访问这块选择的是EFCore+Mysql.使用EF的话不可避免要和DbContext打交道,在Core中的常 ...
- Asp.Net Core下的开源任务调度平台ScheduleMaster
从何说起 2017年初的时候,由于当时项目需要做了一个乞丐版定时调度系统,那时候只在单机上实现了核心的调度功能.做这个玩意之前也调研了社区中开源的解决方案,找了几个实地部署试跑了一下,其实都很不错.但 ...
- ASP.NET MVC不可或缺的部分——DI(IOC)容器及控制器重构的剖析
ASP.NET MVC不可或缺的部分——DI(IOC)容器及控制器重构的剖析 IoC框架最本质的东西:反射或者EMIT来实例化对象.然后我们可以加上缓存,或者一些策略来控制对象的生命周期,比如是否 ...
- Core官方DI剖析(1)--ServiceProvider类和ServiceCollection类
前段时间看了蒋老师的Core文章,对于DI那一块感觉挺有意思,然后就看了一下Core官方DI的源码,这也算是第一个看得懂大部分源码的框架,虽然官方DI相对来说特别简单, 官方DI相对于其它框架(例如 ...
- ASP.NET Core 运行原理剖析2:Startup 和 Middleware(中间件)
ASP.NET Core 运行原理剖析2:Startup 和 Middleware(中间件) Startup Class 1.Startup Constructor(构造函数) 2.Configure ...
- 深入剖析 redis AOF 持久化策略
本篇主要讲的是 AOF 持久化,了解 AOF 的数据组织方式和运作机制.redis 主要在 aof.c 中实现 AOF 的操作. 数据结构 rio redis AOF 持久化同样借助了 struct ...
- 控制反转IOC与依赖注入DI【转】
转自:http://my.oschina.net/1pei/blog/492601 一直对控制反转.依赖注入不太明白,看到这篇文章感觉有点懂了,介绍的很详细. 1. IoC理论的背景我们都知道,在采用 ...
- WCF技术剖析之七:如何实现WCF与EnterLib PIAB、Unity之间的集成
原文:WCF技术剖析之七:如何实现WCF与EnterLib PIAB.Unity之间的集成 在这之前,我写过深入介绍MS EnterLib PIAB的文章(参阅<MS Enterprise Li ...
随机推荐
- 【转】一看你就懂,超详细java中的ClassLoader详解
http://blog.csdn.net/briblue/article/details/54973413 ClassLoader翻译过来就是类加载器,普通的java开发者其实用到的不多,但对于某些框 ...
- CodeForces - 598A Tricky Sum (数学,快速幂的运用)
传送门: http://codeforces.com/problemset/problem/598/A A. Tricky Sum time limit per test 1 second memor ...
- sql得到表中的列信息
取列全部用的 sys. 中的表 CTE:WITH name AS() 用法: sql树形查询 ①主键信息 SELECT ic.column_id, ic.index_column_id, ic.o ...
- Python条件判断
计算机之所以能做很多自动化的任务,因为它可以自己做条件判断. 比如,输入用户年龄,根据年龄打印不同的内容,在Python程序中,用if语句实现: age = 20 if age >= 18: p ...
- 重置按钮_reset
function formreset(form){ for(var i=0;i<frmMain.length;i++){ if(frmMain.item(i).type=="text& ...
- 蓝牙实现对等网络连接 <GameKit/GameKit.h>
/* 1.设置UI界面 2.引入框架 3.点击选择照片 4.连接蓝牙设备 5.实现蓝牙的代理方法 6.发送照片 */ #import "ViewController.h" #imp ...
- Java的内存--存储(1)
有次去面试,面试官突然问我这个问题,当时我只知道怎么写最优化,但是具体不知道为什么那样写,身价立马下降哦 1. 以下开发习惯,你怎么看? for(int i=0;i<2;i++){ Person ...
- POJ 1113--Wall(计算凸包)
Wall Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 40363 Accepted: 13754 Description On ...
- 【前行&赛时总结】◇第2站&赛时·8◇ Atcoder ABC-109
[第2站&赛时·8] ABC-109 把最后一题题意理解错了……在第二组数据卡了好久(然而并不知道是special judge)QwQ 最终AK,速度慢了一些 Rank:357 Rating: ...
- 浅谈css蒙版效果
我们进网站浏览时经常看到当鼠标悬浮在图片上或者某一个地方时,会出现一层朦胧现象覆盖着悬浮位置,简单的理解为“蒙版效果”.下面简单列举实现过程: HTML: CSS: