BeanFactory介绍
例如下面的代码使用一个
FileSystemResource来创建一个
XmlBeanFactouy,其中Bean的定义来自文件系统中的XML文件:
使用应用上下文:
它俩的区别是
FileSystemXmlApplicationContext
只能从指定的路径中寻找foo.
xml
文件,而
ClassPathXmlApplicationContext
可以在整个类路径(包括jar文件)中寻找foo,
xml
文件。无论哪种实现使用
getBean
()方法获取Bean。
创建一个简单的Bean
下面是在Spring配置文件中如何配置的:
通过构造函数注入:
注入Bean属性
装配集合:
collection.xml配置文件:
自动装配:Spring提供了四种自动装配类型:
Bean范围化:
大部分情况保留范围化设置是默认的singleton,但是对于新的域对象实例,在使用Spring作为厂时,可能会使用prototype。
利用工厂方法来创建Bean:
初始化和销毁Bean:创建一个Instrumentalist类,此类有初始化方法和销毁方法:
现在需要一个方法来确保在创建Instrumentalist时tuneInstrument()方法被调用,以及在销毁对象时会调用cleanInstrument()方法。为此在生命kenny Bean时...
默认的初始化和销毁方法:如果一个上下文定义文件中有多个Bean都是用相同的方法来初始化和销毁,则没有必要给每个Bean都声明初始化和销毁方法。
作为init-method和destroy-method的备选,我们还可以实现两个Spring接口InitializingBean和DisposableBean。
正如其名字所暗示的,Bean工厂采用了工厂设计模式。就是说,这个类负责创建和分发Bean。在Spring中有几种BeanFactory的实现。其中最常用的是org.springframework.beans.factory.xml.XmlBeanFactory,她根据XML文件中的定义装在Bean。
要创建
XmlBeanFactory
,学要传递一个org.springframework.core.io.Resource实例给构造函数。此Resource对象提供XML文件工厂。Spring提供了有应的Resource实现。如下表所示:
Resource实现 | 目的 |
org.springframework.core.io.ByteArrayResource | 定义内容由一组字节给定的资源 |
org.springframework.core.io.ClassPathResource | 定义可从classpath提取的资源 |
org.springframework.core.io.DescruptiveResource | 定义包含资源描述符但是实际没有可读资源的资源 |
org.springframework.core.io.FileSystemResource | 定义可从文件系统提取的资源 |
org.springframework.core.io.InputStreamResource | 定义可从输入流提取的资源 |
org.springframework.web.portlet.context.PortletContextResource | 定义可用在portlet上下文中的资源 |
org.springframework.web.context.support.ServletContextResource | 定义可用在servlet上下文中的资源 |
org.springframework.core.io.UrlResource | 定义可从给定URL提取的资源 |
BeanFactory factory = new XmlBeanFactory(new FileSystemResource("c:/beans.xml")); MyBean myBean = (MyBean)factory.getBean("myBean"); |
BeanFactory
对简单的应用来说已经很好了,但是为了获得Spring框架的强大功能,你需要使用Spring的更加高级的容器——应用上下文。
表面上
ApplicationContext
和
BeanFactory
差不多。两者都是载入Bean定义信息,装配Bean,根据需要分发Bean。但是
ApplicationContext
提供了更多功能:
- 文本信息解析工具,包括对国际化(I18N)的支持。
- 提供了载入文件资源的通用方法,如载入图片。
- 可以向注册为监听去的Bean发送事件。
在
ApplicationContext
的诸多实现中欧冠,有三个实现经常用到:
- ClassPathXmlApplicationcContext——从类路径中的XML文件载入上下文定义信息,把上下文定义文件当成类路径资源。
- FileSystemXmlApplicationContext——从文件系统中的XML文件载入上下文定义信息。
- XmlWebApplicationContext——从Web系统中的XML文件载入下上文定义信息。
基于Web的Spring中要介绍XmlWebApplicationContext,这里简单的介绍
ClassPathXmlApplicationcContext
和
FileSystemXmlApplicationContext
,如下面代码所示:
ApplicationContext ctx = new FileSystemXmlApplicationContext("foo.xml"); ApplicationContext ctx = new ClassPathXmlApplicationContext("foo.xml"); |
创建Bean
生命一个接口:
public interface Performer { void perform() throws PerformanceException; } |
package com.springinaction.springidol; public class Juggler implements Performer { private int beanBags = 3; public Juggler() {} public juggler(int beanBags) { this.beanBags = beanBags; } public void perform() throws PerformanceException { System.out.println("JUGGLING" + beanBags + "BEANBAGS"): } } |
<bean id="duke" class="com.springinaction.springidol.Juggler" /> |
<bean id="duke" class="com.springinaction.springidol.Juggler"> <constructor-arg value="15" /> </bean> |
public interface Instrument { void play(); } public class Saxophone implements Instrument { public Saxophone() {} public void play() { System.out.println("TOOT TOOT TOOT"); } } publci class Instrumentalist implement Performer { public Instrumentalist() {} public void perform() throws PerformanceException { System.out.print("Playing" + song + ":"); instrument.play(); } private int age; public void setSong(int age) { this.age= age; } private String song; public void setSong(String song) { this.song = song; } private Instrument instrument; public void setInstrument (Instrument instrument) { this.instrument= instrument; } } |
<bean id="instrument" class="com.springinaction.springidol.Saxophone" /> <bean id="kenny" class="com.springinaction.springidol.Instrumentalist"> <property name="age" value="37" /> <property name="song" value="Jingle Bells" /> <property name="instrument" value="instrument" /> </bean> |
装配集合:
package org.spring.beans.collection;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
public class OneManBand implements Performer {
public OneManBand(){}
public void perform() {
System.out.println("---------------List--------------------");
for(Instrument instrument : instruments){
instrument.play();
}
System.out.println("---------------Set--------------------");
for(Instrument instrument : instruments2){
instrument.play();
}
System.out.println("---------------Map--------------------");
for(String key : instruments3.keySet()){
System.out.print(key+" : ");
Instrument instrument = instruments3.get(key);
instrument.play();
}
System.out.println("------------Properties----------------");
for(Iterator iter = instruments4.keySet().iterator();iter.hasNext();){
String key = (String)iter.next();
System.out.println(key+" : " + instruments4.getProperty(key));
}
}
private Collection<Instrument> instruments;
public void setInstruments(Collection<Instrument> instruments) {
this.instruments = instruments;
}
private Collection<Instrument> instruments2;
public void setInstruments2(Collection<Instrument> instruments2) {
this.instruments2 = instruments2;
}
private Map<String,Instrument> instruments3;
public void setInstruments3(Map<String,Instrument> instruments3) {
this.instruments3 = instruments3;
}
private Properties instruments4;
public void setInstruments4(Properties instruments4) {
this.instruments4 = instruments4;
}
}
|
<bean id="Hank" class="org.spring.beans.collection.OneManBand">
<property name="instruments">
<list>
<ref bean="guitar"/>
<ref bean="cymbal"/>
<ref bean="harmonica" />
</list>
</property>
<property name="instruments2">
<set>
<ref bean="guitar"/>
<ref bean="cymbal"/>
<ref bean="harmonica" />
<ref bean="harmonica" />
</set>
</property>
<property name="instruments3">
<map>
<entry key="GUITAR" value-ref="guitar" />
<entry key="CYMBAL" value-ref="cymbal" />
<entry key="HARMONICA" value-ref="harmonica" />
</map>
</property>
<property name="instruments4">
<props>
<prop key="GUITAR">STRUM STRUM STRUM</prop>
<prop key="CYMBAL">CRASH CRASH CRASH</prop>
<prop key="HARMONICA">HUM HUM HUM</prop>
</props>
</property>
</bean>
<bean id="guitar" class="org.spring.beans.collection.Saxophone">
<property name="str" value="STRUM STRUM STRUM" />
</bean>
<bean id="cymbal" class="org.spring.beans.collection.Saxophone">
<property name="str" value="CRASH CRASH CRASH" />
</bean>
<bean id="harmonica" class="org.spring.beans.collection.Saxophone">
<constructor-arg value="HUM HUM HUM"></constructor-arg>
</bean>
|
public class CollectionApp {
public static void main(String[] args){
ApplicationContext ctx = new ClassPathXmlApplicationContext("org/spring/beans/collection/collection.xml");
Performer performer = (Performer)ctx.getBean("Hank");
performer.perform();
}
}
|
- byName——试图在容器中寻找和需要自动装配的属性名相同的Bean(或ID)。如果没有找到相符的Bean,这个属性就没有被装配上。
- byType——试图在容器中寻找一个与需要自动配置的属性类型相同的Bean,如果没有找到相符的Bean,这个属性就没有被装配。如果找到超过一个相符的Bean,会抛出org.springframework.bans.factory.UnsatisfiedDependencyException异常。
- constructor——试图在容器中查找与需要自动装配的Bean的构造函数参数一致的一个或多个Bean,如果存在不确定bean或构造函数,容器会抛出异常org.springframework.bans.factory.UnsatisfiedDependencyException。
- autodetect——首先尝试使用constructor来自动装配,然后使用byType方式,不确定性的处理与constructor方式和byType方式一样。
当在Spring中生命<bean>时,有声明Bean范围的选项。为了湿的每次都能产生一个新的Bean实例,可以声明Bean的scope属性为prototype。例如:
<bean id="saxophone" class="org.spring.beans.collection.Saxophone" scope="prototype" /> |
范围 | 完成任务 |
singleton | 定义Bean的范围为每个Spring容器一个实例(默认值) |
Prototype | 允许Bean可以被多次实例化(使用一次就创建一个) |
request | 定义Bean的范围是HTTP请求。只有使用有web能力的Spring上下文(例如Spring MVC)时才有效 |
session | 定义Bean的范围是HTTP会话。只有使用有web能力的Spring上下文(例如Spring MVC)时才有效 |
plobal-session | 定义Bean的范围是全局HTTP会话。只有在portlet上下文中才有效 |
很多时候,在Spring应用上下文中配置的Bean都可以通过调用类的构造函数来创建。当然,可以使用公共的构造函数来创建,但是如果想通过静态厂方法,使用第三方API来展现某些类型,该怎么做?Stage类是单例类的基本示例:
package org.spring.beans.controlbean;
public class Stage {
private Stage() {}
//简单的装在实例
private static class StageSingletonHolder {
static Stage instance = new Stage();
}
//返回实例
public static Stage getInstance() {
return StageSingletonHolder.instance;
}
}
|
为了确保没有其他方法可以创建Stage的多个实例:
<bean id="theStage" class="org.spring.beans.controlbean.Stage" factory-method="getInstance" /> |
package org.spring.beans.controlbean;
public class Instrumentalist {
private Instrument instrument;
public Instrument getInstrument() {
return instrument;
}
public void setInstrument(Instrument instrument) {
this.instrument = instrument;
}
public void tuneInstrument() {
instrument.tune();
}
public void cleanInstrument() {
instrument.clean();
}
}
|
<bean id="kenny" class="org.spring.beans.controlbean.Instrumentalist"
init-method="tuneInstrument" destroy-method="cleanInstrument">
<property name="instrument" ref="saxophone" />
</bean>
|
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"
default-init-method="initInstrument"
default-destroy-method="cleanInstrument">
</beans>
|