我们来看一个老式Java对象POJO的例子:
package com.habuma.spring;
public class HelloWorldBean{
public String sayHelllo(){
return "Hello World";
}
}
DI
spring的一项重要作用就是依赖注入,我们可以DI来装配上面的POJO式代码,来帮助应用对象彼此之间保持松散耦合。
它的意义在于:在实际的应用中,有两个或者两个以上的类组成,它们需要相互协作来完成特定的功能。每个对象负责管理与自己
相互协作的对象(即它所依赖的对象)的引用,这样会导致高度耦合和难以测试代码。
我们来看一个紧耦合的例子:
package com.springinaction.knight;
public class DamselRescuingKnight implements knight{
private RescueDameselQuest quest;
public DamselRescuingKnight(){
this.quest=new RescueDamselQuest();//与RescueDamselQuest紧耦合
}
public void embarkOnQuest(){
quest.embark();
}
}
这样的紧耦合有两个缺点,一方面DamselRescuingKnight与RescueDameselQuest耦合在一起,这样限制了这个骑士的能力。另一方面耦合的代码
难以测试,难以复用和理解。
这时DI可以很好的解决这两个问题,依赖注入会将所依赖的关系自动交给目标对象,而不是让对象自己去获取依赖。我们来看下面的例子:
package com.springinaction.knights;
public class BraveKnight implements Knight{
private Quest quest
public BraveKnight(Quest quest){//Quest被注入进来,BraveKnight没有自行创建探险任务,而是把它作为构造器参数注入,这就是构造器注入。
//这里的任务类型是Quest,这样所有探险任务都实现一个接口,BraveKnight就可以做RescueDamselQuest、SlayDragonQuest等任意Quest的实现。
this.quest=quest;
}
public void embarkOnQuest(){
quest.embark();
}
}
对依赖进行替换最常用的方法就是在测试的时候使用mock实现。测试代码就不详细说明了。
让我们来看如何把特定的探险任务传给骑士:
package com.springination.knights;
import java.io.printStream;
public class SlayDragonQuest implements Quest{
private printstream stream;
public SlayDragonQuest(printstream stream){
this.stream=stream;
}
public void embark(){
stream.println("Embarking on quest to slay the dragon!");
}
}
装配
创建应用组件之间协作的行为我们称为装配。Spring有多种装配bean的方式,采用XML是很常见的一种装配方式。
我们来看下面这个配置文件knights.xml,将BraveKnight、SlayDragonQuest和PrintsStream装配到一起。
<?xml version="1.0" encoding==‘UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns="http://www-instance.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="knight" class="com.springinaction.knights.BraveKnight">
<constructor-arg ref="quest"/>//注入Quest bean
</bean>
<bean id="quest" class="com.springinaction.knights.SlayDragonQuest">
<constructor-arg value="#{T(System).out}"/>
</bean>
</bean>