简介
在Spring中两个最基本最重要的包是orgspringframeworkbeans和orgntext包这两个包中的代码为Spring的反向控制特性(也叫作依赖注射)提供了基础BeanFactory[ springframework/beans/factory/l]提供了能够管理任何种类beans(对象)的先进的配置机制潜在地利用任何一种存储设备ApplicationContext建立在BeanFactory之上并增加了其他的功能比如同Spring AOP特性更容易整合信息资源处理(用于国际化)事件传播声明式机制用于创建ApplicationContext和可选的父上下文以及与应用层相关的上下文(比如WebApplicationContext)以及其他的增强
简而言之BeanFactory提供了配置框架和基本的功能而ApplicationContext为它增加了更强的功能这些功能中的一些或许更加JEE和企业中心(enterprisecentric)一般来说ApplicationContext是BeanFactory的完全超集任何BeanFactory功能和行为的描述也同样被认为适用于ApplicationContext
用户有时在特定的场合下不确定BeanFactory和ApplicationContext哪一个更适于使用通常大部分在JEE环境中构建的应用最好的选择是使用ApplicationContext因为它不仅提供了BeanFactory所有的特性以及它自己附加的特性而且还提供更声明化的方法去使用一些功能这通常是令人满意的你最好选择BeanFactory的主要场景通常是当内存使用是最主要的关注(比如在一个每kb都要计算的applet中)而且你也不需要ApplicationContext所有特性的时候
这一章粗略地分为两部分第一部分包括同时适用于BeanFactory和ApplicationContext的基本原则第二部分会包括仅仅适用于ApplicationContext的一些特性
.BeanFactory和Bean定义(基础)
.BeanFactory
BeanFactory是实际上实例化配置和管理许多beans的容器这些beans通常互相之间合作因而也在它们之间产生依赖这些依赖反映在被BeanFactory使用的配置数据中(一些依赖可能不像配置数据一样可见而更可能在运行期作为bean之间程序交互的函数)
一个BeanFactory用接口orgspringframeworkbeansfactoryBeanFactory表示这个接口有多个实现最常使用的的简单的BeanFactory实现是orgspringframeworkbeansfactoryxmlXmlBeanFactory(这带有如下的暗示ApplicationContext是BeanFactory的子类所以大多数的用户更喜欢使用ApplicationContext的XML形式)
尽管对于大多数场景几乎所有的被BeanFactory管理的用户代码不需要知道BeanFactory但是BeanFactory还是不得不实例化这一步可以通过如下清楚的用户代码发生
InputStream is = new FileInputStream(beansxml);
XmlBeanFactory factory = new XmlBeanFactory(is);
或者
ClassPathResource res = new ClassPathResource(beansxml);
XmlBeanFactory factory = new XmlBeanFactory(res);
或者
ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(
new String[] {applicationContextxml applicationContextpartxml});
// of course an ApplicationContext is just a BeanFactory
BeanFactory factory = (BeanFactory) appContext;
对于很多的应用场景用户代码不需要实例化BeanFactory因为Spring框架代码会做这件事举例来说web层提供支持代码用来自动读取一个Spring ApplicationContext并把读取过程作为一个JEE web应用启动过程的一部分这个声明式的过程在这里描述
编程式地操纵BeanFactory将会在后面接受下面部分将集中描述BeanFactory的配置
在最基础的级别上一个BeanFactory配置由一个或多个BeanFactory必须管理的Bean的定义组成在一个XmlBeanFactory中在顶级的<beans>元素中配置一个或多个<bean>元素
<?xml version= encoding=UTF?>
<!DOCTYPE beans PUBLIC //SPRING//DTD BEAN//EN
beansdtd;>
<beans>
<bean id= class=>
</bean>
<bean id= class=>
</bean>
</beans>
.Bean定义
一个XmlBeanFactory实体中的Bean定义包括如下的细节以及其他一些信息
l 一个classname通常这是Bean定义中描述的那个bean的真正的实现类然而如果一个bean使用一个静态工厂方法所创建而不是被普通的构造函数创建那么这里实际上就是工厂类的classname
l Bean行为配置元素声明这个bean在容器的行为方式(比如prototype或singleton自动装配模式依赖检查模式初始化和析构方法)
l 构造函数参数和需要赋予新创建bean的属性举一个例子一个管理连接池的bean使用的连接数目(即可以指定为一个property也可以作为一个构造函数参数)或者池大小的限制数目
l 这个bean需要起作用的其他beans比如它的合作者(同业也可以作为属性或者构造函数的参数)这个也被叫做依赖
上面列出的概念直接转化为组成bean定义的一组元素这些元素在下面的表格中列出关于它们每一个的更详细的说明都有一个链接相对应
表Bean定义说明
特性 更多信息
class 节bean class
id和name 节bean标志符(id和name)
singleton或prototype 节使用singleton还是不使用呢
构造函数参数 节设置bean的属性和合作者
bean属性 节设置bean的属性和合作者
自动装配模式 节自动装配合作者
依赖检查模式 节检查依赖
初始化方法 节生命周期接口
析构方法 节生命周期接口
注意bean定义是由真实的接口orgspringframewonfigBeanDefinition以及它的各种子接口和实现所表示的然而绝大多数的用户代码不需要与BeanDefination直接作用
.bean class
class属性通常是强制性的(参看节通过实例工厂方法创建bean和节child bean的定义这两个例外情况)被用来达到两个目的中的一个在绝大多数普通的场景中BeanFactory自己直接调用bean的构造函数来创建bean(相当于调用new的Java代码)class属性指定了需要创建的bean的类在比较少的普通场景中BeanFactory调用某个类的静态的所谓的工厂方法来创建beanclass属性指定了实际包含静态工厂方法的那个类(至于静态工厂方法返回的bean的类型是同一个类还是完全不同的另一个类这并不重要)
.通过构造方法创建bean
当使用构造函数方式创建bean的时候所有普通的类都可以被Spring使用以及同Spring兼容这就是说被创建的类不需要实现任何指定的接口或者按照特定的样式进行编码仅仅指定bean的类就足够了然而由于依赖你给特定bean使用的IoC类型你可能需要一个默认的(空的)构造函数
另外BeanFactory并不局限于管理真正的JavaBeans事实上它也能够管理任何你想让它帮你管理的类虽然很多使用Spring的人喜欢在BeanFactory中用真正的JavaBeans(仅包含一个默认的(无参数的)构造方法以及在属性后面包含适当的相对应的setter和getter)但是在你的BeanFactory中也可以使用特殊的非bean样式的类举例来说如果你需要使用一个遗留下来的完全没有遵守JavaBean规范的连接池不要担心Spring同样能够管理它
使用XmlBeanFactory你可以像如下这样制定你的bean class
<bean id=exampleBean
class=examplesExampleBean/>
<bean name=anotherExample
class=examplesExampleBeanTwo/>
至于为构造方法提供参数(可选的)以及对象实例构造后设置实例的属性将会在后面叙述
.通过静态工厂方法创建Bean
当你定义一个使用静态工厂方法创建的bean同时使用class属性指定包含静态工厂方法的类这个时候就需要另一个叫做factorymethod的属性来指定工厂方法的名字Spring期待能够调用这个方法(包含可选的一组参数将在后面叙述)并且返回一个有效的对象之后这个对象就会如同用构造方法创建的对象一样被看待用户可以使用这样的bean定义在遗留代码中调用静态工厂
下面是一个bean定义的例子声明了一个bean要通过调用一个工厂方法被创建要注意定义并没有指定返回对象的类型只指定包含工厂方法的类在这个例子中createInstance必须是静态方法
<bean id=exampleBean
class=examplesExampleBean
factorymethod=createInstance/>
至于为工厂方法提供参数(可选的)以及对象实例被工厂方法返回后设置该实例的属性将会在后面叙述
.通过实例工厂方法创建bean
与使用静态工厂方法创建bean非常类似的是使用一个实例工厂方法(非静态的)通过调用一个已存在bean(这个bean应该是工厂类型)的工厂方法来创建新的bean
要使用这种机制class属性必须保留为空的而且factorybean属性必须指定一个包含工厂方法的bean的name(¥¥)而工厂方法本身仍然要通过factorymethod属性设置
下面是一个例子
<! The factory bean which contains a method called
createInstance >