Spring有两种不同的容器:BeanFactory和ApplicationContext。
BeanFactory提供基本的IoC支持。ApplicationContext是基于BeanFactory之上的,提供了应用程序框架服务,例如从properties文件中读取信息等。
Spring提供了BeanFactory和ApplicationContext的多个实现。
2.1.1 BeanFactory介绍
BeanFactory由org.springframework.beans.factory.BeanFactory接口定义。BeanFactory是工厂模式(Factory pattern)的实现,因此BeanFactory负责创建和分发bean。BeanFactory不仅仅是创建和分发bean,它同时还负责在实例化bean时创建bean之间的联系。BeanFactory还可以参与到bean的生命周期中,它可以调用对象的初始化函数和析构函数(自行定义的函数,在xml中指定为析构函数)。
Spring中最常用的是XmlBeanFactory。
假设Greeting接口定义了方法sayHello();GreetingImpl实现了Greeting接口。XML文件定义如下:
<?xml version = "1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTDBEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="greetingService"
class="GreetingImpl">
<property name="greeting">
<value>Hello</value>
</property>
</bean>
</beans>
/***interface Greeting********/
public interface Greeting{
public void sayHello();
}
/****class GreetingImpl*********/
public class GreetingImpl implements Greeting{
public GreetingImpl () {
}
private String greeting;
public void sayHello(){
System.out.println(greeting);
}
public void setGreeting(String helloWord){
greeting=helloWord;
}
}
/****class ExecutableApp***********/
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
public class ExecutableApp {
public ExecutableApp () {
}
public static void main(String args[]){
FileSystemResource fileSystemResource = new FileSystemResource("configuration.xml");
BeanFactory factory = new XmlBeanFactory(fileSystemResource);
Greeting personA = (Greeting)factory.getBean("greetingService");
personA.sayHello();
}
}
注:上述程序中红色的部分在Spring-framework-1.2.5运行通过。和Spring in action中的不同。
该程序的运行结果是:Hello。
BeanFactory factory = new XmlBeanFactory(fileSystemResource);
该语句从configuration.xml文件中读取bean的定义,但是并不立即实例化bean,直到需要使用这些bean的时候,才会实例化他们。在上面的例子中,实例化是在调用factory.getBean()的时候进行的。例如,我们将GreetingImpl修改成为
public class GreetingImpl implements Greeting{
public GreetingImpl () {
System.out.println("Instance GreetingImpl object");
}
……
}
将ExecutableApp修改为
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.FileSystemResource;
public class ExecutableApp {
public ExecutableApp () {
}
public static void main(String args[]){
System.out.println(“Before load xml file”);
FileSystemResource fileSystemResource = new FileSystemResource("configuration.xml");
BeanFactory factory = new XmlBeanFactory(fileSystemResource);
System.out.println(“After load xml file”);
Greeting personA = (Greeting)factory.getBean("greetingService");
personA.sayHello();
}
}
运行结果为:
Before load xml file
After load xml file
Instance GreetingImpl object
Hello
也就是说,在装载bean的定义的时候,BeanFactory并没有实例化bean。
“需要使用这些bean的时候”并不是只包括调用getBean方法的时候。在上面的例子中,我们加入一个新的接口及其实现:
public interface Person {
public String getName();
}
public class MrSmith implements Person{
private String name="Mr Smith";
public MrSmith() {
System.out.println("Instance MrSmith object");
}
public String getName(){
return name;
}
}
修改configuration.xml文件和GreetingImpl类:
public class GreetingImpl implements Greeting{
public GreetingImpl () {
System.out.println("Instance GreetingImpl object");
}
private String greeting;
Person who;
public void sayHello(){
System.out.println(greeting + “,” + who.getName());
}
public void setGreeting(String helloWord){
greeting=helloWord;
}
public void setWho(Person who){
this.who=who;
}
}
<?xml version = "1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTDBEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="person" class="MrSmith"/>
<bean id="greetingService"
class="GreetingImpl">
<property name="greeting">
<value>Hello</value>
</property>
<property name="who”>
<ref bean="person"/>
</property>
</bean>
</beans>
在运行ExecutableApp时,输出的结果是:
Before load xml file
After load xml file
Instance GreetingImpl object
Instance MrSmith object
Hello,Mr Smith
首先实例化的是GreetingImpl类,然后实例化了MrSmith类。我们在ExecutableApp中并没有调用getBean来生成MrSmith类,但是在xml文件的greetingService bean的定义中,我们应用了person bean,因此也生成了MrSmith类的实例。