依赖注入: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>三、两种注入方式的对比 建议采用以设值注入为主,构造注入为辅的注入策略。对于依赖关系无须变化的注入,尽量采用构造注入;而其他的依赖关系的注入,则考虑采用设值注入。