如何理解控制反转和依赖注入

文章目录

  • 如何理解控制反转和依赖注入
  • 前言
  • 一、什么是控制反转
    • 1.何为依赖关系
    • 2.进行控制反转的前的一些准备
    • 3.控制反转的简单实现
      • 2.1:实现代码
  • 二、什么是依赖注入?
    • 1.与控制反转的联系。
  • 总结

前言

Spring框架广泛应用于实际开发中,但是其中概念性的"控制反转",和"依赖注入"却很少有人能够说明白,甚至有的文章会说“控制反转”=“依赖注入”,这其实是不对的,因为两者虽然在实现代码上很相似,但其中蕴含的思想,所关注的问题还是不同的。


一、什么是控制反转

从这个词上理解,控制反转就是程序放弃对自己依赖的控制,把控制权交给第三方工厂。

1.何为依赖关系

代码如下:

 Class ServiceImpl1 implements IService{private IMyDao dao=new MydaoImpl1();public void save(){System.out.println("我是 ServiceImpl1");dao.save();}}

我们可以看到,在这个Service类中执行save()方法时,调用的其实是另一个类MyDao的save()方法,像这种A类中持有一个B类成员变量的情况,我们称作A类依赖B类。

2.进行控制反转的前的一些准备

细心的小伙伴可以发现,上面的代码有一个接口的细节,本例中接口有如下的继承关系。控制反转的概念和继承的关系不大,这里主要是为了讲解之后的依赖注入。

 interface IService {public void save();}
///Class ServiceImpl1 implements IService{private IMyDao dao=new MydaoImpl1();public void save(){System.out.println("我是 ServiceImpl1");dao.save();}}
/interface IMyDao {public void save();}
///Class MydaoImpl1 implements IMyDao{public void save(){System.out.println("执行了保存操作");}}}

两个接口 IMyDao和IService。
两个实现类 MydaoImpl1 和 ServiceImpl1。
实现类重写接口的save()方法。

3.控制反转的简单实现

我们自己写一个工厂类,在程序中用工厂类来创建对象。达到下图所示的效果:

 // IMyDao dao=new MydaoImpl1();          不用在程序里new!!!IMyDao dao=BeanFactory.getBean("dao",IMyDao.class);

这里大家可能会疑惑,这里依旧还是要手写给dao赋值啊,只不过是在BeanFactory中new了而已,之前直接new就行了,现在还得多写一个工厂类,这不是多此一举吗?当然不是,工厂类是根据配置文件来创建对应实例的,也就是说,通过BeanFactory.getBean(),我们把控制权交给了配置文件。这样做的好处显而易见:如果我们需要更改一个依赖,我们再也不用关心它的依赖究竟是在哪一行new的,只需要关心new的是什么,并在配置文件中设置好就行了。

有人可能会说,不就是不关心在哪new吗?这能有什么用?的却,在例子中我们可以很清晰的看到程序是在哪里new的依赖。但是,当类之间的依赖关系变多时,依赖管理就会变得相当繁琐,而这些繁琐的操作,一个工厂就能全部解决并有效管理,实在是香到了极点。

2.1:实现代码

首先,我们需要一个配置文件,本案例中使用 .properties文件作为配置文件。
配置文件解决的基本问题是:1.用哪个名字取出类?2.取出的是什么类?

//  用 ”dao“ 取出类,取出 com.services.impl.MydaoImpl1 这个类dao=com.services.impl.MydaoImpl1//这里也可以写其他的Key-value对//key可以随便取名,value必须是实现类的全限定类名!!注意!全限定类名!!//因为要用Class.forName();反射获取类的实例,所以一定要是全限定类名!!//有时大家会用Anntation,java是能解析到其注解的类的!类名,返回类型,返回类型的泛型...//凡是你能想到的信息注解都能解析到,所以注解模式会相对精简。

好了,我们写了一个及其简单的配置文件,注意前文提到的

 Class MydaoImpl1 implements IMyDao

现在让我们来创建一个工厂:
(逻辑很简单,谁看谁知道)

 public class BeanFactory {private static Properties props;         //解析配置文件的类private static Map<String,Object> beans; //存放实例的容器(单例模式)/* 先来个静态代码块,确保加载工厂时就能加载配置文件 */static {beans=new HashMap<String, Object>();  //准备好容器props=new Properties();//获取配置文件的输入流//如何获取不重要,你甚至能用in=new FileInputStream(new File(Path p))InputStream in=BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");try{props.load(in);                  //这里我们就能取出配置文件中的数据了Enumeration keys=props.keys();   //获取所有的名字。//循环遍历所有的keywhile (keys.hasMoreElements()){String key=keys.nextElement().toString(); //当前的key取出来String beanName=props.get(key).toString();//依据key取出对应的全限定类名//使用反射,调用类声明的无参构造方法实例化一个类Object bean=Class.forName(beanName).getDeclaredConstructor().newInstance();beans.put(key,bean);    //将实例化的类放入容器}}catch (Exception e) {throw new ExceptionInInitializerError("初始化BeanFactory失败");}finally{in.close();  //记得关闭流,这里应该有个try,懒得写了。}}///来个静态方法,返回咱们容器中的实例。//使用泛型,免得返回后还要强制类型转换public static <T>T getBean getBean(String name,Class<T> clazz){///大家看!我们此时的name就是配置文件中的keyreturn (T)beans.get(name);}}

好啦!我们有了工厂!
然我们返回第一张图!我们可以这样写了!

Class ServiceImpl1 implements IService{//private IMyDao dao=new MydaoImpl1();  不用这个啦!!万岁!private IMyDao dao=BeanFactory.getBean("dao",IMyDao.class);public void save(){System.out.println("我是 ServiceImpl1");dao.save();}}

相信到这里,你已经发现了,控制反转的核心思想就是” 不 new!“
我们如果需要一个新的实现类,再也不用自己new啦,编写一个IMyDao的实现类,然后配置文件的 “dao=自己实现类的全限定类名” 就行啦。怎么样,控制权是不是到了配置文件手上?这种控制权的转移,用控制反转来描述,是不是很形象!

二、什么是依赖注入?

简单来说,就是依赖别写成具体的实现类,而是写成接口。

1.与控制反转的联系。

我们返回上面的代码,

 private IMyDao dao=BeanFactory.getBean("dao",IMyDao.class);

大家思考一下,如果写成这样行不行?

 private MydaoImpl1 dao=BeanFactory.getBean("dao",MydaoImpl1.class);

从执行上来说,二者没有区别。
但是,第一种的耦合性比第二种低!
如果使用第一种方法,我们只要继承了IMyDao接口,就可以在配置文件中调用相应的类了。第二种方法是做不到这一点的,因为它把实现类写死了。
嗯,这似乎是给一个空的IMyDao dao注入了一个具体的实现类,dao不就是serviece中的依赖嘛,这就是一个依赖注入啊。
那么,我们不给IMyDao dao赋予一个初始值。而是通过set方法,或是构造函数给dao动态的进行赋值行不行呢?当然当然可以啊!而且实现也很简单。

 Class ServiceImpl1 implements IService{//private IMyDao dao=new MydaoImpl1();  不用这个啦!!万岁!private IMyDao dao;//默认构造函数public ServiceImpl1(){dao=BeanFactory.getBean("dao",IMyDao.class);}//或者这样public ServiceImpl1(IMyDao dao){this.dao=dao;}//再来个setpublic void setDao(IMyDao dao){this.dao=dao;}public void save(){System.out.println("我是 ServiceImpl1");dao.save();}}

总结

控制反转的核心就是获取对象实例 不 new ! ,而是使用工厂!
依赖注入的核心是依赖的类 用接口! 注入其实现类!

如何理解控制反转和依赖注入相关推荐

  1. 控制反转和依赖注入的理解

    什么是控制反转(IOC) 平时我们使用类的对象,需要自己new一个 然后调用.控制反转就是不自己实例化 而是交给第三方实例化,这里的第三方就叫做IOC容器. 控制反转这个名字就是相对于我们平时的使用模 ...

  2. php程序设计依赖注入_PHP控制反转和依赖注入

    [TOC] PHP和依赖注入 理论知识 要了解控制反转( Inversion of Control ), 我觉得有必要先了解软件设计的一个重要思想:依赖倒置原则(Dependency Inversio ...

  3. 架构设计之依赖倒置、控制反转与依赖注入

    名词解释 依赖:一种模型元素之间的关系的描述.例如类A调用了类B,那么我们说类A依赖于类B. 耦合:一种模型元素之间的关系的描述.例如类A调用了类B或类B调用了类A,那么我们说类A与类B有耦合关系. ...

  4. .NET Core ASP.NET Core Basic 1-2 控制反转与依赖注入

    本节内容为控制反转与依赖注入 简介 控制反转IOC 这个内容事实上在我们的C#高级篇就已经有所讲解,控制反转是一种设计模式,你可以这样理解控制反转,假设有一个人他有一部A品牌手机,他用手机进行听歌.打 ...

  5. 控制反转_.NET Core ASP.NET Core Basic 12 控制反转与依赖注入

    本节内容为控制反转与依赖注入 简介 控制反转IOC 这个内容事实上在我们的C#高级篇就已经有所讲解,控制反转是一种设计模式,你可以这样理解控制反转,假设有一个人他有一部A品牌手机,他用手机进行听歌.打 ...

  6. IOC控制反转(依赖注入思想)

    IOC控制反转(依赖注入思想) 获取map 类型的 request session application 的方法: 实现RequestAware,SessionAware,ApplicationAw ...

  7. 一篇文章讲透控制反转和依赖注入

    https://www.jianshu.com/p/07af9dbbbc4b 转载链接:http://blog.xiaohansong.com/2015/10/21/IoC-and-DI/# http ...

  8. 依赖倒置、控制反转、依赖注入

    实现依赖倒置.控制反转.依赖注入的核心思想是:接口驱动 接口驱动有很多好处,可以提供不同灵活的子类实现,增加代码稳定和健壮性,实现模块之间的解耦等等. 参考资料:https://www.cnblogs ...

  9. Java 控制反转和依赖注入模式【翻译】【整理】

    Inversion of Control Containers and the Dependency Injection pattern --Martin Fowler 本文内容 Component ...

最新文章

  1. android View未渲染时获得高度
  2. 分享20个非常有用的Web开发工具和框架
  3. 汇编: mul乘法指令
  4. 【Python3网络爬虫开发实战】3-基本库的使用 1.2-处理异常
  5. 在python语言中下列是二进制整数_Python从菜鸟到高手(5):数字
  6. 学Java技术,这些问题要避免!
  7. SpringBoot之AOP详解
  8. C++中的long long和__int64类型(转载)
  9. Hololens开发入门篇-郑洪智-专题视频课程
  10. Java经典算法题(一,kafka权威指南百度网盘
  11. 细胞自动机,那是什么?
  12. 几个函数泰勒展开式及其记忆技巧
  13. MIDI音乐编程那些事儿
  14. Windows11电脑触摸屏不能用怎么修复
  15. \t\t【团队精神】荣辱与共 交流分享 精诚协作 尊重理解 ——程序员应知
  16. 程序人生 - 敬酒常识
  17. 想用QQ小程序流量主广告赚钱,你需要知道的知识!
  18. geoCoordMap数据,全国省市,4个直辖市,用于echart gl 3d地图
  19. phpMyAdmin 3.4.3正式版拨开云雾见青天
  20. 微分方程中的自洽系统(Autonomous system)

热门文章

  1. 不到 20 行 Python 代码,轻松玩转波士顿矩阵图!
  2. 二十一Redis集群
  3. VS在引用外库运行时显示无法解析外部符号
  4. ipad怎样和计算机连接网络,ipad怎么连接电脑教程 ipad怎么和电脑连接【详细步骤】...
  5. C#语言实例源码系列-调用OutLokk发送邮件
  6. CentOS7.9安装rsyslog+loganalyzer日志服务器详细配置
  7. parsing XML document from class path resource [applicationContext.xml]…
  8. python tkmessagebox_[Python] tk json 做的GUI 人人影视下载资源解析
  9. 反恐精英服务器维护到几点,CSOL4月22日更新维护公告 停机维护到几点
  10. 单位矩阵在乘法运算中相当于1