【转】跟我一起学Spring 3(4)–深入理解IoC(控制反转)和DI(依赖注入)
在继续下面的章节之前,我们要先说说大名鼎鼎的IoC和DI。
我们经常会听说IoC,也就是Inversion of Controller,控制反转。事实上,IoC并不是一个新鲜的概念,最早可能是在1988年,由Ralph E. Johnson和Brian Foote在论文Designing Reusable Classes中提出。IoC从字面上来说有两个内容,一个是控制,一个是反转。那么什么是控制呢?又是怎样反转的呢?
为了更好的理解,我们用个实例来说明吧。下面的程序有一个Example
类,它含有一个doStuff()
方法来完成某件事情。注意,以下的代码都是截取的片段,并不完整。
如果采用传统的编程:
Example.java
public class Example { private DataFinder dataFinder; public Example(){
dataFinder = new MysqlDataFinder();
} public void doStuff() {
// 此处具体实现省略
...
dataFinder.getData();
...
} }
此外提供一个DataFinder
接口:
DataFinder.java
public interface DataFinder {
void getData();
}
MysqlDataFinder实现:
MysqlDataFinder.java
public class MysqlDataFinder implements DataFinder{ @Override
public void getData() {
...
}
}
最后有个Main方法:
Client.java
public class Client { public static void main(String[] args){ Example example = new Example();
example.doStuff(); }
}
现在问题来了,因为DataFinder
接口有很多不同的实现,譬如可以读取Mysql数据库中的数据MysqlDataFinder
,还可能读取Oracle数据库中的数据的OracleDataFinder
。它们都实现了DataFinder
接口,并有各自的getData()
实现。我们要想读取不同的数据源中的数据,就需要实现不同的Example类:
public class Example1 { private DataFinder dataFinder; public Example1(){
dataFinder = new MysqlDataFinder();
} public void doStuff() {
// 此处具体实现省略
...
dataFinder.getData();
...
}
} public class Example2 { private DataFinder dataFinder; public Example2(){
dataFinder = new OracleDataFinder();
} public void doStuff() {
// 此处具体实现省略
...
dataFinder.getData();
...
} } public class Client { public static void main(String[] args){ Example example1 = new Example1();
example1.doStuff(); Example example2 = new Example2();
example2.doStuff();
}
}
图片一 传统方法的类图
Example既依赖于接口DataFinder
,又同时依赖实现,因为它需要在编译阶段就确定使用哪种实现,这样显然缺乏灵活性,会产生很多重复的代码,有没有更好的方法减少重复呢?我们首先想到,可以在Example构造器中给个参数,来控制实现的DataFinder类型:
public class Example { private DataFinder dataFinder; public Example(){
} public Example(int type){
if(type == 1){
dataFinder = new MysqlDataFinder();
}else if(type == 2){
dataFinder = new OracleDataFinder();
}
} public void doStuff() {
// 此处具体实现省略
...
dataFinder.getData();
...
}
} public class Client { public static void main(String[] args){ Example example1 = new Example(1);
example1.doStuff(); Example example2 = new Example(2);
example2.doStuff();
}
}
现在代码变得简单了,但Example类依然依赖具体的实现,实际上Example并不应该有这么多的控制逻辑,它应该只负责调用doStuff()方法来完成工作,至于用什么类型的DataFinder不应该是它考虑的问题。我们试着将控制调用哪种类型DataFinder的任务交给Client类。
public class Example { private DataFinder dataFinder; public Example(){
} public Example(DataFinder dataFinder){
this.dataFinder = dataFinder;
} public void doStuff() {
// 此处具体实现省略
...
dataFinder.getData();
...
}
} public class Client { public static void main(String[] args){ Example example1 = new Example(new MysqlDataFinder());
example1.doStuff(); Example example2 = new Example(new OracleDataFinder());
example2.doStuff();
}
}
图片二 控制反转模式的类图
这样Example不用依赖具体的实现了,不用管到底是用哪种类型的DataFinder。换句话说,就是将调用类Example类对于选择哪个具体DataFinder的控制权从其中移除,转交给Client决定,实现了“控制”的“反转”,这也就是我们所说的IoC。
我们现在知道了控制反转,我们可以把它看作是一个概念。而依赖注入(Dependency Injection)是控制反转的一种实现方法。James Shore给出了依赖注入的定义:依赖注入就是将实例变量传入到一个对象中去(Dependency injection means giving an object its instance variables)。
Spring的核心就是依赖注入。Spring支持的注入方式主要有两种:setter注入(setter injection)和构造器注入(constructor injection)。我们上面的代码便是使用的构造器注入
。关于注入的这两种方式请查看后续章节。此外,对于控制反转还有另外一种实现: service locator。有兴趣的可以研究一下。
传统编程和IoC的对比
- 传统编程:决定使用哪个具体的实现类的控制权在调用类本身,在编译阶段就确定了。
- IoC模式:调用类只依赖接口,而不依赖具体的实现类,减少了耦合。控制权交给了容器,在运行的时候才由容器决定将具体的实现动态的“注入”到调用类的对象中。
【转】跟我一起学Spring 3(4)–深入理解IoC(控制反转)和DI(依赖注入)的更多相关文章
- Spring的三大核心思想:IOC(控制反转),DI(依赖注入),AOP(面向切面编程)
Spring核心思想,IoC与DI详解(如果还不明白,放弃java吧) 1.IoC是什么? IoC(Inversion of Control)控制反转,IoC是一种新的Java编程模式,目前很多 ...
- Spring-初识Spring框架-IOC控制反转(DI依赖注入)
---恢复内容开始--- IOC :控制反转 (DI:依赖注入)使用ioc模式开发 实体类必须有无参构造方法1.搭建Spring环境下载jarhttp://maven.springframework. ...
- 学习Spring IOC控制反转和DI依赖注入总结
30岁的小曹,20岁的身体,还在坚持在能力允许控制范围内22点睡觉,5点起床锻炼身体,好好学习,除了加班或者像今天这样的深夜,再一次写已经有X百万人写过的 spring Ioc 的总结博客. 一.IO ...
- Spring框架系列(四)--IOC控制反转和DI依赖注入
背景: 如果对象的引用或者依赖关系的管理由具体对象完成,代码的耦合性就会很高,代码测试也变得困难.而IOC可以很好的解决这个问题,把这 些依赖关系交给框架或者IOC容器进行管理,简化了开发. IOC是 ...
- 三大框架 之 Spring(IOC控制反转、DI依赖注入)
目录 常用词汇 left join与left outer join的区别 Struts2的标签库导入 Spring Spring概述 什么是Spring spring特点 下载 IOC 什么IOC 传 ...
- spring(一) IOC 控制反转 、DI 依赖注入
IOC 控制反转:创建对象的方式 变成了由Spring来主导 IOC底层原理:对象工厂 1.导入jar包:4个核心jar和1个依赖jar spring-beans-4.3.9.RELEASE.jar ...
- [Spring]IOC控制反转和DI依赖注入
从之前算起到现在接触Spring也已经有几天了,进度也不是很快,就只弄懂了控制反转和依赖注入那么一点东西.然后敲了两个demo 主要是因为之前没有学过,然后网上资源很多但是都不是面向我们初学者的,大多 ...
- spring.net (1) 概念-控制反转(又名依赖注入)
Spring.net 作为一个应用程序框架,在构建企业级.net应用程序提供了很多灵活而又丰富的功能(如:依赖注入,aop,数据访问抽象,asp.net 扩展). 控制反转: Inversion of ...
- Spring Boot笔记十:IOC控制反转
目录 IOC控制反转和DI依赖注入 IOC实现Hello World Spring IOC容器怎么知道哪些是管理的对象? IOC容器getBean方法的三种签名 xml配置文件的import导入 @A ...
随机推荐
- Unite 2017 | 从《闹闹天宫》看MOBA游戏里的网络同步技术
http://mp.weixin.qq.com/s/0v0EU79Q6rFafrh8ptlmhw 在Unite 2017 Shanghai案例分享专场,来自蓝港互动<闹闹天宫>项目组的主程 ...
- SharePoint SPUtility.SendEmail 发送邮件设置级别
前言 熟悉sharepoint开发的都知道,sharepoint默认有个发送邮件的方法,不过,最近有个需求,用户希望发送邮件的时候,带上邮件的级别. 经过研究,发现有下面的办法,可以添加邮件的发送级别 ...
- 快速找到自己想要用到的cocos2d-x的缓冲动画
游戏中在做很多动画时,需要用到缓冲来增强表现.比如宝箱"鼓"几下,然后"蹦"的一下打开.很多时候要调效果时,需要轮着试,如果有一张图和实际示例效果,那就省很多事 ...
- 低版本系统兼容的ActionBar(四)添加Tab+添加自定义的Tab视图+Fragment
在ActionBar中添加Tab是很有用的技巧.在support V7库的支持下,我们几乎可以用和之前一样的方式来添加Tab,对于Tab来说,我们可以和MenuItem一样,给他定义自己的视图.我这里 ...
- 通知栏消息(Notification)初步
Notification是用来在通知中心中显示信息的,这里讲解了其最简单的使用方式. 关于PendingIntent和Intent的区别可以参考这篇文章:http://blog.csdn.net ...
- [Android Security] 静态分析Android程序——smali文件解析
cp : https://blog.csdn.net/hp910315/article/details/51823236 cp : http://www.jb51.net/softjc/119036. ...
- MySQL中的information_schema数据库表说明
MySQL 中的 information_schema 数据库 版权声明:https://blog.csdn.net/kikajack/article/details/80065753 1. 概述 ...
- Spring Data JPA 实现多表关联查询
本文地址:https://liuyanzhao.com/6978.html 最近抽出时间来做博客,数据库操作使用的是 JPA,相对比 Mybatis 而言,JPA 单表操作非常方便,增删改查都已经写好 ...
- iOS:在tableView中通过Masonry使用autolayout在iOS7系统出现约束崩溃
一.出现崩溃情景: 给tableView创建一个头视图,也即tableHeaderView,然后使用Masonry并切换到iOS7/7.1系统给tableHeaderView中的所有子视图添加约束,此 ...
- Focal Loss(RetinaNet) 与 OHEM
Focal Loss for Dense Object Detection-RetinaNet YOLO和SSD可以算one-stage算法里的佼佼者,加上R-CNN系列算法,这几种算法可以说是目标检 ...