依赖注入:Dependency Injection
控制反转:Inversion of Control
一、设值注入
public interface Person
... {
public void useAxe();
}
public interface Axe
... {
public void chop();
}
Person的实现类代码如下:
public class Chinese implements Person
... {
//面向Axe接口编程,而不是具体的实现类
private Axe axe;
//默认的构造器
public Chinese() ...{}
//设值注入所需的setter方法
public void setAxe(Axe axe) ...{
this.axe = axe;
}
//实现Person接口的useAxe方法
public void useAxe() ...{
System.out.println(axe.chop());
}
}
Axe的第一个实现类代码如下:
public class StoneAxe implements Axe
... {
public StoneAxe() ...{}
//实现Axe接口的chop方法
public String chop() ...{
return "石斧砍柴好慢";
}
}
下面采用Spring的配置文件将Person实例和Axe实例组织在一起。
<? xml version = " 1.0 " encoding = " gb2312 " ?>
<! DOCTYPE beans PUBLIC " -//SPRING//DTD BEAN//EN "
" http://www.springframework.org/dtd/spring-beans.dtd " >
< beans >
< bean id = " chinese " class = " prolove.Chinese " >
<!-- property元素用来指定需要容器注入的属性,axe属性需要容器
注入。此处是设值注入,因此Chinese类必须拥有setAxe方法 -->
< property name = " axe " >
<!-- 此处将另一个bean的引用注入给chinese bean -->
< ref local = " stoneAxe " />
</ property >
</ bean >
< bean id = " stoneAxe " class = " prolove.StoneAxe " />
</ beans >
下面是主程序部分:
public class BeanTest
... {
public static void main(String[] args) throws Exception...{
//因为是独立的应用程序,显式实例化Spring的上下文
ApplicationContext ctx =
new FileSystemXmlApplicationContext("bean.xml");
//通过Person bean的id来获取bean实例,面向接口编程,因此
//此处强制类型转换为接口类型
Person p = (Person)ctx.getBean("chinese");
//直接执行Person的useAxe()方法
p.useAxe();
}
}
下面也给出了使用Ant编译和运行该应用的简单脚本:
<? xml version = " 1.0 " ?>
< project name = " spring " basedir = " . " default = "" >
< path id = " classpath " >
< fileset dir = " ....lib " >
< include name = " *.jar " />
</ fileset >
< pathelement path = " . " />
</ path >
< target name = " compile " description = " Compile all source code " >
< javac destdir = " . " debug = " true "
deprecation = " false " optimize = " false " failonerror = " true " >
< src path = " . " />
< classpath refid = " classpath " />
</ javac >
</ target >
< target name = " run " description = " run the main class " depends = " compile " >
< java classname = " prolove.BeanTest " fork = " yes " failonerror = " true " >
< classpath refid = " classpath " />
</ java >
</ target >
</ project >
Axe的另一个实现类如下:
public class SteelAxe implements Axe
... {
public SteelAxe() ...{}
public String chop() ...{
return "钢斧砍柴真快";
}
}
Spring配置:
< bean id = " steelAxe " class = " prolove.SteelAxe " />
< ref local = " steelAxe " />
二、构造注入
public class Chinese implements Person
... {
//面向Axe接口编程,而不是具体的实现类
private Axe axe;
//默认的构造器
public Chinese() ...{}
//构造注入所需的带参数的构造器
public Chinese(Axe axe) ...{
this.axe = axe;
}
//实现Person接口的useAxe方法
public void useAxe() ...{
System.out.println(axe.chop());
}
}
<? xml version = " 1.0 " encoding = " gb2312 " ?>
<! DOCTYPE beans PUBLIC " -//SPRING//DTD BEAN//EN "
" http://www.springframework.org/dtd/spring-beans.dtd " >
< beans >
< bean id = " chinese " class = " prolove.Chinese " >
< constructor - arg >< ref bean = " stoneAxe " /></ constructor - arg >
</ bean >
< bean id = " stoneAxe " class = " prolove.StoneAxe " />
</ beans >
三、两种注入方式的对比
建议采用以设值注入为主,构造注入为辅的注入策略。对于依赖关系无须
变化的注入,尽量采用构造注入;而其他的依赖关系的注入,则考虑采用设值注入。
控制反转:Inversion of Control
一、设值注入
public interface Person
... {
public void useAxe();
}
public interface Axe
... {
public void chop();
}
Person的实现类代码如下:
public class Chinese implements Person
... {
//面向Axe接口编程,而不是具体的实现类
private Axe axe;
//默认的构造器
public Chinese() ...{}
//设值注入所需的setter方法
public void setAxe(Axe axe) ...{
this.axe = axe;
}
//实现Person接口的useAxe方法
public void useAxe() ...{
System.out.println(axe.chop());
}
}
Axe的第一个实现类代码如下:
public class StoneAxe implements Axe
... {
public StoneAxe() ...{}
//实现Axe接口的chop方法
public String chop() ...{
return "石斧砍柴好慢";
}
}
下面采用Spring的配置文件将Person实例和Axe实例组织在一起。
<? xml version = " 1.0 " encoding = " gb2312 " ?>
<! DOCTYPE beans PUBLIC " -//SPRING//DTD BEAN//EN "
" http://www.springframework.org/dtd/spring-beans.dtd " >
< beans >
< bean id = " chinese " class = " prolove.Chinese " >
<!-- property元素用来指定需要容器注入的属性,axe属性需要容器
注入。此处是设值注入,因此Chinese类必须拥有setAxe方法 -->
< property name = " axe " >
<!-- 此处将另一个bean的引用注入给chinese bean -->
< ref local = " stoneAxe " />
</ property >
</ bean >
< bean id = " stoneAxe " class = " prolove.StoneAxe " />
</ beans >
下面是主程序部分:
public class BeanTest
... {
public static void main(String[] args) throws Exception...{
//因为是独立的应用程序,显式实例化Spring的上下文
ApplicationContext ctx =
new FileSystemXmlApplicationContext("bean.xml");
//通过Person bean的id来获取bean实例,面向接口编程,因此
//此处强制类型转换为接口类型
Person p = (Person)ctx.getBean("chinese");
//直接执行Person的useAxe()方法
p.useAxe();
}
}
下面也给出了使用Ant编译和运行该应用的简单脚本:
<? xml version = " 1.0 " ?>
< project name = " spring " basedir = " . " default = "" >
< path id = " classpath " >
< fileset dir = " ....lib " >
< include name = " *.jar " />
</ fileset >
< pathelement path = " . " />
</ path >
< target name = " compile " description = " Compile all source code " >
< javac destdir = " . " debug = " true "
deprecation = " false " optimize = " false " failonerror = " true " >
< src path = " . " />
< classpath refid = " classpath " />
</ javac >
</ target >
< target name = " run " description = " run the main class " depends = " compile " >
< java classname = " prolove.BeanTest " fork = " yes " failonerror = " true " >
< classpath refid = " classpath " />
</ java >
</ target >
</ project >
Axe的另一个实现类如下:
public class SteelAxe implements Axe
... {
public SteelAxe() ...{}
public String chop() ...{
return "钢斧砍柴真快";
}
}
Spring配置:
< bean id = " steelAxe " class = " prolove.SteelAxe " />
< ref local = " steelAxe " />
二、构造注入
public class Chinese implements Person
... {
//面向Axe接口编程,而不是具体的实现类
private Axe axe;
//默认的构造器
public Chinese() ...{}
//构造注入所需的带参数的构造器
public Chinese(Axe axe) ...{
this.axe = axe;
}
//实现Person接口的useAxe方法
public void useAxe() ...{
System.out.println(axe.chop());
}
}
<? xml version = " 1.0 " encoding = " gb2312 " ?>
<! DOCTYPE beans PUBLIC " -//SPRING//DTD BEAN//EN "
" http://www.springframework.org/dtd/spring-beans.dtd " >
< beans >
< bean id = " chinese " class = " prolove.Chinese " >
< constructor - arg >< ref bean = " stoneAxe " /></ constructor - arg >
</ bean >
< bean id = " stoneAxe " class = " prolove.StoneAxe " />
</ beans >
三、两种注入方式的对比
建议采用以设值注入为主,构造注入为辅的注入策略。对于依赖关系无须
变化的注入,尽量采用构造注入;而其他的依赖关系的注入,则考虑采用设值注入。