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