本案例中使用 XML 文档配置进行 Dependency Injection 的实现。
Spring 容器的主要功能包括:
这个案例中其他的代码沿用了 Spring IoC 简单案例 部分代码。
本案例中需要两个功能:
提供每日锻炼(已经在 IoC 中实现的功能)
提供每日幸运语
这一部分需要实现一个新的帮助函数(依赖):ForuneService
Spring 中提供了好几种依赖注入的方法,主要的有三种:
本案例中会使用 构造函数和 setter 注入进行实现。
开发过程:
定义依赖 interface 和实现类
FortuneService interface:
package springdemo;
public interface FortuneService {
public String getFortune();
}
新的实现类:
package springdemo;
public class HappyFortuneService implements FortuneService {
@Override
public String getFortune() {
return "Today is your lucky day";
}
}
修改之前的 interface:
package springdemo;
public interface Coach {
public String getDailyWorkout();
public String getDailyFortune();
}
package springdemo;
public class BaseballCoach implements Coach {
@Override
public String getDailyWorkout() {
return "Spend 30 minutes on batting practice.";
}
@Override
public String getDailyFortune() {
return null;
}
}
package springdemo;
public class TrackCoach implements Coach {
@Override
public String getDailyWorkout() {
return "Run a hrad 5k.";
}
@Override
public String getDailyFortune() {
return null;
}
}
在实现类中创造一个构造函数让 Spring 实现注入
package springdemo;
public class TrackCoach implements Coach {
// define a private field for the dependency
private FortuneService fortuneService;
// define a constructor for dependency injection
public TrackCoach(FortuneService fortuneService) {
this.fortuneService = fortuneService;
}
@Override
public String getDailyWorkout() {
return "Run a hrad 5k.";
}
@Override
public String getDailyFortune() {
// use my fortuneService to get a fortune
return fortuneService.getFortune();
}
}
在 Spring 配置文件中注入依赖
<bean id="myFortune" class="springdemo.HappyFortuneService">bean>
<bean id="myCoach" class="springdemo.TrackCoach">
<constructor-arg ref="myFortune" />
bean>
这时候运行结果如下:

XML 中的内容最终在 Spring 内部转化为对应的 Java 代码,创建对应的对象和传入参数:
HappyFortuneService myFortuneService = new HappyFortuneService();
BaseballCoach myCoach = new BaseballCoach(myFortuneService);
这里会创建一个新的类以及新的主函数进行实现。
开发流程:
在类中创建 setter 进行依赖注入
package springdemo;
public class CricketCoach implements Coach {
private FortuneService fortuneService;
public FortuneService getFortuneService() {
return fortuneService;
}
public void setFortuneService(FortuneService fortuneService) {
System.out.println("CricketCoach: inside setter method");
this.fortuneService = fortuneService;
}
public CricketCoach() {
System.out.println("CricketCoach: inside no-arg constructor");
}
@Override
public String getDailyWorkout() {
return "Practice fast bowling for 15 minutes";
}
@Override
public String getDailyFortune() {
return fortuneService.getFortune();
}
}
在 Spring 配置文件中完成依赖注入
<bean id="myFortuneService" class="springdemo.HappyFortuneService">bean>
<bean id="myCricketCoach" class="springdemo.CricketCoach">
<property name="fortuneService" ref="myFortuneService" />
bean>
对应新的 Main 函数:
package springdemo;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SetterDemoApp {
public static void main(String[] args) {
// load the spring configuration file
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
// retrieve bean from spring container
Coach theCoach = context.getBean("myCricketCoach", Coach.class);
// call methods on the bean
System.out.println(theCoach.getDailyWorkout());
// call new method for fortune
System.out.println(theCoach.getDailyFortune());
// close the context
context.close();
}
}
运行结果:

Spring 也可以通过配置文件注入字面值。
开发过程:
在类中创建 setter 进行依赖注入
新增邮箱和队伍属性:
package springdemo;
public class CricketCoach implements Coach {
private FortuneService fortuneService;
private String emailAddress;
private String team;
public FortuneService getFortuneService() {
return fortuneService;
}
public CricketCoach() {
System.out.println("CricketCoach: inside no-arg constructor");
}
public void setFortuneService(FortuneService fortuneService) {
System.out.println("CricketCoach: inside setter method");
this.fortuneService = fortuneService;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
public String getTeam() {
return team;
}
public void setTeam(String team) {
this.team = team;
}
@Override
public String getDailyWorkout() {
return "Practice fast bowling for 15 minutes";
}
@Override
public String getDailyFortune() {
return fortuneService.getFortune();
}
}
在 Spring 配置文件中完成依赖注入
<bean id="myCricketCoach" class="springdemo.CricketCoach">
<property name="fortuneService" ref="myFortuneService" />
<property name="emailAddress" value="test@test.com">property>
<property name="team" value="Yankee">property>
bean>
更新主函数:
package springdemo;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class SetterDemoApp {
public static void main(String[] args) {
// load the spring configuration file
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
// retrieve bean from spring container
CricketCoach theCoach = context.getBean("myCricketCoach", CricketCoach.class);
// call methods on the bean
System.out.println(theCoach.getDailyWorkout());
// call new method for fortune
System.out.println(theCoach.getDailyFortune());
System.out.println(theCoach.getEmailAddress());
System.out.println(theCoach.getTeam());
// close the context
context.close();
}
}
运行结果:

除了直接在 Spring 配置文件中注入字面值之外,Spring 还能通过在 Spring 配置文件中读取其他配置文件的方式,更加动态地获取字面值。
开发流程如下:
新建属性文件
foo.email=email@properties.com
foo.team=Team From Properties File
在 Spring 配置文件中加载属性文件
🚰属性文件
<context:property-placeholder location="classpath:sport.properties" />
<bean id="myCricketCoach" class="springdemo.CricketCoach">
<property name="fortuneService" ref="myFortuneService" />
<property name="emailAddress" value="${foo.email}" />
<property name="team" value="${foo.team}" />
bean>
运行结果如下:
