开始学习Spring的时候,对依赖注入(DI)——也叫控制反转(IOC)—— 的理解不是很深刻。随着学习的深入,也逐渐有了自己的认识,在此记录,也希望能帮助其他入门同学更深入地理解Spring。本文不再介绍其背景与定义,比 如“究竟是什么控制被反转了?”、“注入了什么依赖?”等等问题,在网络上应该会搜出很多相关的内容。本文下面主要从入门者的角度来分析如下问题:“依赖 注入要解决什么问题?” 以及 “依赖注入可能是如何实现的?”

==============================

为了更好地解释这两个问题,本文列举了一个简单的代码小例子来配合说明,先将例子中设计的类列举如下:

比如我有苹果(Apple)、橘子(Orange)、香蕉(Banana)三种水果(Fruit),我想知道某种水果是什么颜色的。

对应水果类的实现代码非常简单:

Fruit是个接口:

package com.example.impl;

public interface Fruit {
//只有一个简单的方法:返回水果的颜色
public String getColor();
}

Apple、Banana、Orange三个类各自实现Fruit接口:

package com.example.action;
import com.example.impl.Fruit; public class Apple implements Fruit {
public String getColor() {
return "Red";
}
} --------------------------------------------
package com.example.action;
import com.example.impl.Fruit; public class Banana implements Fruit {
public String getColor() {
return "Yellow";
}
} --------------------------------------------
package com.example.action;
import com.example.impl.Fruit; public class Orange implements Fruit {
public String getColor() {
return "Orange";
}
}

==============================

OK,现在开始解释文章开头提出的两个问题:

(1)依赖注入要解决什么问题?

简单地说,依赖注入就是为了“对类之间的依赖进行解耦”。

比如上面的水果例子中,如果现在我想知道某种水果的颜色,我需要这样实现:

package com.example.test;
import com.example.impl.Fruit;
import com.example.action.*; public class Person {
public static void main(String[] args) {
//我想知道苹果的颜色.
Fruit fruit = new Apple();
System.out.println(fruit.getColor());
}
}

这里,我(Person)与水果类(这里具体为Apple)之间是有依赖的,即Person依赖Fruit,如果我现在想知道香蕉的颜色,那我只能修改Person类的代码如下:

package com.example.test;
import com.example.impl.Fruit;
import com.example.action.*; public class Person {
public static void main(String[] args) {
//我现在改成想知道香蕉的颜色了...
Fruit fruit = new Banana();
System.out.println(fruit.getColor());
}
}

这就是依赖产生的问题:我每次都必须修改Person的代码,才能实现“知道不同Fruit的颜色”的目的。

依赖注入要解决的就是上面这个问题,套在本例中就是:如果我想知道不同Fruit的颜色,我不需要修改Person的代码。也就是Person与Fruit解耦啦!!

那依赖注入具体是怎么实现的呢?且继续往下看。

(2)依赖注入可能是如何实现的?

之所以加“可能”二字,是因为我还没拜读过Spring的内部代码,所以暂时是靠自己的理解认为是这么实现的,但我估计应该八九不离十吧。

上面例子中说到,Person现在是对Fruit有依赖,Spring第一个想到的就是引入Java的反射机制,关于反射本文不再解释,直接拿过来用了,引入反射之后,Person的代码会变成这样:

package com.example.test;
import com.example.impl.Fruit;
import com.example.action.*; public class Person {
public static void main(String[] args) {
try {
//使用Java反射机制,使Person对Fruit具体类的依赖,转变为对类名的字符串的依赖...
Fruit fruit = (Fruit) Class.forName("com.example.action.Apple").newInstance(); //注意:forName()需要传入类的全路径名称
System.out.println(fruit.getColor());
}
catch (Exception e) {
System.out.println("class not found.");
}
}
}

代码看起来复杂了很多,但实际上只有标红的一行是最主要的变化,其余都是异常处理的代码。

可以看到,这个时候,Person对Fruit的依赖,已经转变成了对Fruit下面某个具体类的类名字符串的依赖了,即上面代码中,那段蓝色的字符串。如果此时我想知道橘子的颜色,我只需要把上面蓝色字符串的内容改成:com.example.action.Orange即可。

但是,现在Person还是没有完全摆脱对Fruit的依赖,只是依赖变成了一个字符串而已,那Spring第二个想到的就是通过文件读取这个类名字符串了,我们先在D盘建立一个test.txt文件,然后把“com.example.action.Apple”这段内容写到这个test.txt文件中,同时代码改为:

package com.example.test;
import com.example.impl.Fruit;
import com.example.action.*; public class Person {
public static void main(String[] args) {
try {
FileReader fr = new FileReader("D://test.txt");
BufferedReader br = new BufferedReader(fr);
String fruitName = br.readLine();
//使用Java反射机制,使Person对Fruit具体类的依赖,转变为对类名的字符串的依赖...
//加上读取文件的配置,类名字符串是从文件中读取的,不直接写在Person中
Fruit fruit = (Fruit) Class.forName(fruitName).newInstance(); //注意:forName()需要传入类的全路径名称
System.out.println(fruit.getColor()); br.close();
fr.close();
}
catch (Exception e) {
System.out.println("class not found.");
}
}
}

上面代码其实就是从D://test.txt中读取第一行内容,即类名字符串,然后利用java反射机制实例化这个类。

至此,可以看到Person类也不需要依赖Fruit的类名字符串了,转而变成了对D://test.txt这个文件的依赖,但是我们不需要修改这个文件的地址和文件名,只需要修改文件内容,就可以动态地知道不同水果的颜色了。比如我把test.txt的内容改成com.example.action.Banana,运行程序后,自然会打印出Yellow而不再是Red了。

而Spring实际上是把上文的txt文件替换成了xml文件,这样做的好处?xml文件中的标签更容易对类的各种属性进行表述,比如类名、类属性、类属性的值等等,不用像txt中那种没层次关系、需要自己瞎定义了。自然是更方便使用。

Spring实际使用时,大概就是把上面读取文件+反射的过程封装成ApplicationConext类,所以不需要在Person中写这么大段的代码了,而是直接用ApplicationContext和getBean()即可,或者直接用注解的方式更是方便,其实可以理解为Spring是把这些代码都封装到了框架里,不需要我们自己写了。

以上就是我在学习Spring依赖注入的过程中,一些自己的心得体会,希望大家多多交流、多提意见和建议!

浅析“依赖注入(DI)/控制反转(IOC)”的实现思路的更多相关文章

  1. 依赖注入 DI 控制反转 IOC MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  2. ADO.NET .net core2.0添加json文件并转化成类注入控制器使用 简单了解 iTextSharp实现HTML to PDF ASP.NET MVC 中 Autofac依赖注入DI 控制反转IOC 了解一下 C# AutoMapper 了解一下

    ADO.NET   一.ADO.NET概要 ADO.NET是.NET框架中的重要组件,主要用于完成C#应用程序访问数据库 二.ADO.NET的组成 ①System.Data  → DataTable, ...

  3. 依赖注入 DI 控制反转 IOC 概念 案例 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  4. ASP.NET MVC 中 Autofac依赖注入DI 控制反转IOC 了解一下

    先简单了解一这个几个 名词的意思. 控制反转(IOC) 依赖注入(DI) 并不是某种技术. 而是一种思想.一种面向对象编程法则 什么是控制反转(IOC)?  什么是依赖注入(DI) 可以点击下面链接 ...

  5. ASP.NET中IOC容器Autofac(依赖注入DI 控制反转IOC)

    IOC的一个重点是在程序运行中,动态的向某个对象提供它所需要的其他对象.这一点是通过DI来实现的.Autofac则是比较流行的一款IOC容器. IoC和DI有什么关系呢?其实它们是同一个概念的不同角度 ...

  6. 轻松学,浅析依赖倒置(DIP)、控制反转(IOC)和依赖注入(DI) 依赖注入和控制反转的理解,写的太好了。

    轻松学,浅析依赖倒置(DIP).控制反转(IOC)和依赖注入(DI) 2017年07月13日 22:04:39 frank909 阅读数:14269更多 所属专栏: Java 反射基础知识与实战   ...

  7. 浅谈(IOC)依赖注入与控制反转(DI)

    前言:参考了百度文献和https://www.cnblogs.com/liuqifeng/p/11077592.html以及http://www.cnblogs.com/leoo2sk/archive ...

  8. Spring Framework------>version4.3.5.RELAESE----->Reference Documentation学习心得----->Spring Framework的依赖注入和控制反转

    Dependency Injection and Inversion of Control 1.概述: 1.1相关概念 bean:由IoC容器所管理的对象,也即各个类实例化所得对象都叫做bean 控制 ...

  9. 简单解析依赖注入(控制反转)在Spring中的应用

    IoC——Inversion of Control  控制反转DI——Dependency Injection   依赖注入 大家都知道,依赖注入是Spring中非常重要的一种设计模式.可能很多初学者 ...

随机推荐

  1. unity3d中串口的使用

    工作中遇到了串口的问题,通过查资料&实验写出了下面代码: 关于串口的代码我在网上看了好多,一种是用事件来做,另外一种使用线程来做:(经过试验,unity无法用串口自带的事件进行数据读取): 看 ...

  2. HTML5编码规范

    为每个 HTML 页面的第一行添加标准模式(standard mode)的声明,这样能够确保在每个浏览器中拥有一致的展现. 用两个空格来代替制表符(tab) -- 这是唯一能保证在所有环境下获得一致展 ...

  3. python处理地理数据-geopandas和pyshp

    这边博客并不是有关geopandas的教程和pyshp的教程! 使用python来处理地理数据有很多相关的包,最近研究需要处理一些地理数据,然而arcgis的arcpy总是不能令人满意.所以这里说说p ...

  4. Spring Bean后处理器以及容器后处理器【转】

    Bean后处理器:即当spring容器实例化Bean实例之后进行的增强处理. 容器后处理器:对容器本身进行处理,并总是在容器实例化其他任何Bean之前读取配置文件的元数据并可能修改这些数据. 一.Be ...

  5. 如何在UMG蓝图中动态创建控件

    把控件作为UObject即可,在c++中则使用NewObject函数

  6. jquery cookie的用法

    http://www.cnblogs.com/qiantuwuliang/archive/2009/07/19/1526663.html jQuery cookie是个很好的cookie插件,大概的使 ...

  7. Codeforces Round #107 (Div. 2)

    D题 并查集+组合 #include <iostream> #include <cstdio> #include <cstring> using namespace ...

  8. JAVA学习笔记之static——2016.3.10

    static关键字   作用:修饰符,用于修饰成员<成员产量,成员方法>     1'被修饰的成员产量只有一份.     2'被修饰后的成员多了一种方式的访问,除了可以对象调用外,还可以被 ...

  9. Multiple annotations found at this line

    Multiple annotations found at this line 在使用MyEclipse的时候,通过MVN导入项目时候,webapp下面的JSP页面报了如下的错误: 这种情况通常的原因 ...

  10. linux install StarDict

    1. sudo apt-get install stardict 2. Downloads from: http://abloz.com/huzheng/stardict-dic/zh_CN/ 3. ...