DI就是对象通过其他方法得到依赖关系,而不是通过对象本身的方法。
DI得到的最大的好处是松耦合。If an object only knows about its dependencies by their interface (not their implementation or how they were instantiated) then the dependency can be swapped out with a different implementation without the depending object knowing the difference.如果一个对象只通过接口们来知道它的依赖关系(而不是实现或者他们如何初始化的),那么依赖关系可以通过不同的实现来得到,而依靠的对象不需要知道不同处。
例如,Foo类(图1.2)只通过Bar的接口来调用Bar,那么实际如何实现Bar对于Foo来说没有什么重要的。Bar可以是一个本地的POJO类,一个远程接口,一个EJB或者一个测试程序-Foo不需要了解。
如果你感兴趣,那么你一定急于知道如何用代码实现。下面就是。。。
1.3.2 实战Dependency Injection
假设公司的对市场的分析研究的结果,决定你的客户需要一个骑士-这个意思是:他们需要java类来表示骑士。在了解需求后,你知道了他们需要用类来表示亚瑟王的圆桌骑士,他们上船去寻找圣杯。(老外真能瞎想啊)
这是个奇怪的需求,但你已经习惯了市场小组奇怪的想法了。因此,你打开IDE并写下来下面的代码:
List1.5 Knight bean
package com.springinaction.chapter01.knight;
public class KnightOfRoundTable {
private String name;
private HolyGrailQuest quest;
public KnightOfRoundTable(String name) {
this.name = name;
quest = new HolyGrailQuest();
}
public HolyGrail embarkOnQuest() throws GrailNotFoundException{
return quest.embark();
}
}
1.5中,Knight的名字由构造器作为一个参数构造。它的构造器通过初始化了一个HolyGrailQuest来构造了一个骑士的quest。实现HolyGrailQuest很简单
List 1.6
package com.springinaction.chapter01.knight;
public class HolyGrailQuest {
public HolyGrailQuest(){}
public HolyGrail embark() throws GrailNotFoundException{
HolyGrail grail = null;
//Look for grail
retrun grail;
}
}
很满意你的代码,自豪的把代码放入版本控制服务器上。你希望让市场小组看到,但总觉得什么做的不对。半天后你才发现,你没写单元测试。
Knight的单元测试
单元测试总是很有用的….
1.7 code of test
package com.springinaction.chapter01.knight;
import junit.framework.TestCase;
public class KnightOfRoundTableTest extends TestCase {
public void testEmbarkOnQuest() throws GrailNotFoundException {
KnightOfRoundTable knight = new KnightOfRoundTable("Bedivere");
HolyGrail grail = knight.embarkOnQuest();
assertNotNull(grail);
assertTrue(grail.isHoly());
}
}
写完这个test后,你开始写HolyGrailQuest的测试。但在你开始前,你意识到KnightOfRoundTableTest间接的测试了HolyGrailQuest。你还想测试一下偶然情况,如果embark()返回null?如果抛出了异常呢?
谁调用谁?
现在主要原因是KnightOfRoundTable如何得到一个HolyGrailQuest。不论是初始化一个HolyGrailQuest对象还是通过JNDI调用得到的,每一个knight负责得到自己的quest(图1.3所示)。基于这些,每次你测试KnightOfRoundTable,就是间接的测试了HolyGrailQuest。
还有,没法用不同的方法测试HolyGrailQuest不同的行为(例如,返回null或者抛出异常)。要测试的话,只能写一些虚假的代码。但这样就要修改KnightOfRoundTable的代码,然后再改回来。麻烦不?