依赖注入
2016-12-15 00:00
10 查看
1. 依赖
如果在Class A 中,有Class B 的实例,则称Class A 对Class B 有一个依赖。例如下面类Human 中用到一个Father 对象,我们就说类Human 对类Father 有一个依赖。public class Human { ... Father father; ... public Human() { father = new Father(); } }
仔细看这段代码我们会发现存在一些问题:
(1).如果现在要改变father生成方式,如需要用
new Father(String name)初始化father,需要修改Human代码;
(2).如果想测试不同Father对象对Human的影响很困难,因为father的初始化被写死在了Human的构造函数中;
(3).如果
new Father()过程非常缓慢,单测时我们希望用已经初始化好的father对象Mock掉这个过程也很困难。
2. 依赖注入
上面将依赖在构造函数中直接初始化是一种Hard init 方式,弊端在于两个类不够独立,不方便测试。我们还有另外一种Init 方式,如下:public class Human { ... Father father; ... public Human(Father father) { this.father = father; } }
上面代码中,我们将father对象作为构造函数的一个参数传入。在调用Human的构造方法之前外部就已经初始化好了Father对象。像这种非自己主动初始化依赖,而通过外部来传入依赖的方式,我们就称为依赖注入。
现在我们发现上面1中存在的两个问题都很好解决了,简单的说依赖注入主要有两个好处:
(1).解耦,将依赖之间解耦。
(2).因为已经解耦,所以方便做单元测试,尤其是Mock测试
当然,在java中比较简便的方式是通过注解进行依赖注入。
2.实现
依赖注入的实现是通过java的反射原理。像在spring框架中使用的依赖注入,原理就是从xml中读取到类的名称,然后通过反射进行类的实例化,并且同时使用单例、共工厂等设计模式。