Spring Framework 开发参考手册.docx

上传人:b****5 文档编号:3434963 上传时间:2022-11-23 格式:DOCX 页数:39 大小:45.63KB
下载 相关 举报
Spring Framework 开发参考手册.docx_第1页
第1页 / 共39页
Spring Framework 开发参考手册.docx_第2页
第2页 / 共39页
Spring Framework 开发参考手册.docx_第3页
第3页 / 共39页
Spring Framework 开发参考手册.docx_第4页
第4页 / 共39页
Spring Framework 开发参考手册.docx_第5页
第5页 / 共39页
点击查看更多>>
下载资源
资源描述

Spring Framework 开发参考手册.docx

《Spring Framework 开发参考手册.docx》由会员分享,可在线阅读,更多相关《Spring Framework 开发参考手册.docx(39页珍藏版)》请在冰豆网上搜索。

Spring Framework 开发参考手册.docx

SpringFramework开发参考手册

第3章Beans,BeanFactory和ApplicationContext

3.1.简介

在Spring中,两个最基本最重要的包是org.springframework.beans和org.springframework.context.这两个包中的代码为Spring的反向控制特性(也叫作依赖注射)提供了基础。

BeanFactory提供了一种先进的配置机制来管理任何种类bean(对象),这种配置机制考虑到任何一种可能的存储方式。

ApplicationContext建立在BeanFactory之上,并增加了其他的功能,比如更容易同SpringAOP特性整合,消息资源处理(用于国际化),事件传递,以声明的方式创建ApplicationContext,可选的父上下文和与应用层相关的上下文(比如WebApplicationContext),以及其他方面的增强。

简而言之,BeanFactory提供了配置框架和基本的功能,而ApplicationContext为它增加了更强的功能,这些功能中的一些或许更加接近J2EE并且围绕企业级应用。

一般来说,ApplicationContext是BeanFactory的完全超集,任何BeanFactory功能和行为的描述也同样被认为适用于ApplicationContext

用户有时不能确定BeanFactory和ApplicationContext中哪一个在特定场合下更适合。

通常大部分在J2EE环境的应用中,最好选择使用ApplicationContext,因为它不仅提供了BeanFactory所有的特性以及它自己附加的特性,而且还提供以声明的方式使用一些功能,这通常是令人满意的。

BeanFactory主要是在非常关注内存使用的情况下(比如在一个每kb都要计算的applet中)使用,而且你也不需要用到ApplicationContext的所有特性。

这一章粗略地分为两部分,第一部分包括对BeanFactory和ApplicationContext都适用的一些基本原则。

第二部分包括仅仅适用于ApplicationContext的一些特性

3.2.BeanFactory和BeanDefinitions-基础

3.2.1.BeanFactory

BeanFactory实际上是实例化,配置和管理众多bean的容器。

这些bean通常会彼此合作,因而它们之间会产生依赖。

BeanFactory使用的配置数据可以反映这些依赖关系中(一些依赖可能不像配置数据一样可见,而是在运行期作为bean之间程序交互的函数)。

一个BeanFactory可以用接口org.springframework.beans.factory.BeanFactory表示,这个接口有多个实现。

最常使用的的简单的eanFactory实现是org.springframework.beans.factory.xml.XmlBeanFactory。

(这里提醒一下:

ApplicationContext是BeanFactory的子类,所以大多数的用户更喜欢使用ApplicationContext的XML形式)。

虽然大多数情况下,几乎所有被BeanFactory管理的用户代码都不需要知道BeanFactory,但是BeanFactory还是以某种方式实例化。

可以使用下面的代码实例化BeanFactory:

InputStreamis=newFileInputStream("beans.xml");

XmlBeanFactoryfactory=newXmlBeanFactory(is);

或者

ClassPathResourceres=newClassPathResource("beans.xml");

XmlBeanFactoryfactory=newXmlBeanFactory(res);

或者

ClassPathXmlApplicationContextappContext=newClassPathXmlApplicationContext(

newString[]{"applicationContext.xml","applicationContext-part2.xml"});

//ofcourse,anApplicationContextisjustaBeanFactory

BeanFactoryfactory=(BeanFactory)appContext;

很多情况下,用户代码不需要实例化BeanFactory,因为Spring框架代码会做这件事。

例如,web层提供支持代码,在J2EEweb应用启动过程中自动载入一个SpringApplicationContext。

这个声明过程在这里描述:

编程操作BeanFactory将会在后面提到,下面部分将集中描述BeanFactory的配置.

一个最基本的BeanFactory配置由一个或多个它所管理的Bean定义组成。

在一个XmlBeanFactory中,根节点beans中包含一个或多个bean元素。

xmlversion="1.0"encoding="UTF-8"?

>

DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN//EN""http:

//www.springframework.org/dtd/spring-beans.dtd">

...

...

...

3.2.2.BeanDefinition

一个XmlBeanFactory中的Bean定义包括的内容有:

∙classname:

这通常是bean的真正的实现类。

但是如果一个bean使用一个静态工厂方法所创建而不是被普通的构造函数创建,那么这实际上就是工厂类的classname

∙bean行为配置元素:

它声明这个bean在容器的行为方式(比如prototype或singleton,自动装配模式,依赖检查模式,初始化和析构方法)

∙构造函数的参数和新创建bean需要的属性:

举一个例子,一个管理连接池的bean使用的连接数目(即可以指定为一个属性,也可以作为一个构造函数参数),或者池的大小限制

∙和这个bean工作相关的其他bean:

比如它的合作者(同样可以作为属性或者构造函数的参数)。

这个也被叫做依赖。

上面列出的概念直接转化为组成bean定义的一组元素。

这些元素在下面的表格中列出,它们每一个都有更详细的说明的链接。

表3.1.Bean定义的解释

特性

详细说明

class

第3.2.3节“bean的类”

id和name

第3.2.4节“Bean的标志符(id与name)”

singleton或prototype

第3.2.5节“Singleton的使用与否”

构造函数参数

第3.3.1节“设置bean的属性和合作者”

bean的属性

第3.3.1节“设置bean的属性和合作者”

自动装配模式

第3.3.5节“自动装配协作对象”

依赖检查模式

第3.3.6节“依赖检查”

初始化模式

第3.4.1节“生命周期接口”

析构方法

第3.4.1节“生命周期接口”

注意bean定义可以表示为真正的接口org.springframework.beans.factory.config.BeanDefinition以及它的各种子接口和实现。

然而,绝大多数的用户代码不需要与BeanDefination直接接触。

3.2.3.bean的类

class属性通常是强制性的(参考第3.2.3.3节“通过实例工厂方法创建bean”和第3.5节“子bean定义”),有两种用法。

在绝大多数情况下,BeanFactory直接调用bean的构造函数来"new"一个bean(相当于调用new的Java代码),class属性指定了需要创建的bean的类。

在比较少的情况下,BeanFactory调用某个类的静态的工厂方法来创建bean,class属性指定了实际包含静态工厂方法的那个类。

(至于静态工厂方法返回的bean的类型是同一个类还是完全不同的另一个类,这并不重要)。

3.2.3.1.通过构造函数创建bean

当使用构造函数创建bean时,所有普通的类都可以被Spring使用并且和Spring兼容。

这就是说,被创建的类不需要实现任何特定的接口或者按照特定的样式进行编写。

仅仅指定bean的类就足够了。

然而,根据bean使用的IoC类型,你可能需要一个默认的(空的)构造函数。

另外,BeanFactory并不局限于管理真正的JavaBean,它也能管理任何你想让它管理的类。

虽然很多使用Spring的人喜欢在BeanFactory中用真正的JavaBean(仅包含一个默认的(无参数的)构造函数,在属性后面定义相对应的setter和getter方法),但是在你的BeanFactory中也可以使用特殊的非bean样式的类。

举例来说,如果你需要使用一个遗留下来的完全没有遵守JavaBean规范的连接池,不要担心,Spring同样能够管理它。

使用XmlBeanFactory你可以像下面这样定义你的beanclass:

class="examples.ExampleBean"/>

class="examples.ExampleBeanTwo"/>

至于为构造函数提供(可选的)参数,以及对象实例创建后设置实例属性,将会在后面叙述

3.2.3.2.通过静态工厂方法创建Bean

当你定义一个使用静态工厂方法创建的bean,同时使用class属性指定包含静态工厂方法的类,这个时候需要factory-method属性来指定工厂方法名。

Spring调用这个方法(包含一组可选的参数)并返回一个有效的对象,之后这个对象就完全和构造方法创建的对象一样。

用户可以使用这样的bean定义在遗留代码中调用静态工厂。

下面是一个bean定义的例子,声明这个bean要通过factory-method指定的方法创建。

注意这个bean定义并没有指定返回对象的类型,只指定包含工厂方法的类。

在这个例子中,createInstance必须是static方法.

class="examples.ExampleBean2"

factory-method="createInstance"/>

至于为工厂方法提供(可选的)参数,以及对象实例被工厂方法创建后设置实例属性,将会在后面叙述.

3.2.3.3.通过实例工厂方法创建bean

使用一个实例工厂方法(非静态的)创建bean和使用静态工厂方法非常类似,调用一个已存在的bean(这个bean应该是工厂类型)的工厂方法来创建新的bean。

使用这种机制,class属性必须为空,而且factory-bean属性必须指定一个bean的名字,这个bean一定要在当前的bean工厂或者父bean工厂中,并包含工厂方法。

而工厂方法本身仍然要通过factory-method属性设置。

下面是一个例子:

--Thefactorybean,whichcontainsamethodcalled

createInstance-->

class="...">

...

--Thebeantobecreatedviathefactorybean-->

factory-bean="myFactoryBean"

factory-method="createInstance"/>

虽然我们要在后面讨论设置bean的属性,但是这个方法意味着工厂bean本身能够被容器通过依赖注射来管理和配置

3.2.4.Bean的标志符(id与name)

每一个bean都有一个或多个id(也叫作标志符,或名字;这些名词说的是一回事)。

这些id在管理bean的BeanFactory或ApplicationContext中必须是唯一的。

一个bean差不多总是只有一个id,但是如果一个bean有超过一个的id,那么另外的那些本质上可以认为是别名。

在一个XmlBeanFactory中(包括ApplicationContext的形式),你可以用id或者name属性来指定bean的id(s),并且在这两个或其中一个属性中至少指定一个id。

id属性允许你指定一个id,并且它在XMLDTD(定义文档)中作为一个真正的XML元素的ID属性被标记,所以XML解析器能够在其他元素指回向它的时候做一些额外的校验。

正因如此,用id属性指定bean的id是一个比较好的方式。

然而,XML规范严格限定了在XMLID中合法的字符。

通常这并不是真正限制你,但是如果你有必要使用这些字符(在ID中的非法字符),或者你想给bean增加其他的别名,那么你可以通过name属性指定一个或多个id(用逗号,或者分号;分隔)。

3.2.5.Singleton的使用与否

Beans被定义为两种部署模式中的一种:

singleton或non-singleton。

(后一种也别叫作prototype,尽管这个名词用的不精确因为它并不是非常适合)。

如果一个bean是singleton形态的,那么就只有一个共享的实例存在,所有和这个bean定义的id符合的bean请求都会返回这个唯一的、特定的实例。

如果bean以non-singleton,prototype模式部署的话,对这个bean的每次请求都会创建一个新的bean实例。

这对于例如每个user需要一个独立的user对象这样的情况是非常理想的。

Beans默认被部署为singleton模式,除非你指定。

要记住把部署模式变为non-singletion(prototype)后,每一次对这个bean的请求都会导致一个新创建的bean,而这可能并不是你真正想要的。

所以仅仅在绝对需要的时候才把模式改成prototype。

在下面这个例子中,两个bean一个被定义为singleton,而另一个被定义为non-singleton(prototype)。

客户端每次向BeanFactory请求都会创建新的exampleBean,而AnotherExample仅仅被创建一次;在每次对它请求都会返回这个实例的引用。

class="examples.ExampleBean"singleton="false"/>

class="examples.ExampleBeanTwo"singleton="true"/>

注意:

当部署一个bean为prototype模式,这个bean的生命周期就会有稍许改变。

通过定义,Spring无法管理一个non-singleton/prototypebean的整个生命周期,因为当它创建之后,它被交给客户端而且容器根本不再跟踪它了。

当说起non-singleton/prototypebean的时候,你可以把Spring的角色想象成“new”操作符的替代品。

从那之后的任何生命周期方面的事情都由客户端来处理。

BeanFactory中bean的生命周期将会在第3.4.1节“生命周期接口”一节中有更详细的叙述。

3.3.属性,合作者,自动装配和依赖检查

3.3.1.设置bean的属性和合作者

反向控制通常与依赖注入同时提及。

基本的规则是bean通过以下方式来定义它们的依赖(比如它们与之合作的其他对象):

构造函数的参数,工厂方法的参数;当对象实例被构造出来或从一个工厂方法返回后设置在这个实例上的属性。

容器的工作就是创建完bean之后,真正地注入这些依赖。

这完全是和一般控制方式相反的(因此称为反向控制),比如bean实例化,或者直接使用构造函数定位依赖关系,或者类似ServiceLocator模式的东西。

我们不会详细阐述依赖注射的优点,很显然通过使用它:

代码变得非常清晰;当bean不再自己查找他们依赖的类而是由容器提供,甚至不需要知道这些类在哪里以及它们实际上是什么类型,这时高层次的解耦也变得很容易了。

正如上面提到的那样,反向控制/依赖注射存在两种主要的形式:

∙基于setter的依赖注射,是在调用无参的构造函数或无参的静态工厂方法实例化你的bean之后,通过调用你的bean上的setter方法实现的。

在BeanFactory中定义的使用基于setter方法的注射依赖的bean是真正的JavaBean。

Spring一般提倡使用基于setter方法的依赖注射,因为很多的构造函数参数将会是笨重的,尤其在有些属性是可选的情况下。

∙基于构造函数的依赖注射,它是通过调用带有许多参数的构造方法实现的,每个参数表示一个合作者或者属性。

另外,调用带有特定参数的静态工厂方法来构造bean可以被认为差不多等同的,接下来的文字会把构造函数的参数看成和静态工厂方法的参数类似。

虽然Spring一般提倡在大多数情况下使用基于setter的依赖注射,但是Spring还是完全支持基于构造函数的依赖注射,因为你可能想要在那些只提供多参数构造函数并且没有setter方法的遗留的bean上使用Spring。

另外对于一些比较简单的bean,一些人更喜欢使用构造函数方法以确保bean不会处于错误的状态。

BeanFactory同时支持这两种方式将依赖注射到被管理bean中。

(实际上它还支持在一些依赖已经通过构造函数方法注射后再使用setter方法注射依赖)。

依赖的配置是以BeanDefinition的形式出现,它和JavaBeans的PropertyEditors一起使用从而知道如何把属性从一个格式转变为另一个。

真正传送的值被封装为PropertyValue对象。

然而,大多数Spring的使用者并不要直接(比如编程的方式)处理这些类,而更多地使用一个XML定义文件,这个文件会在内部被转变为这些类的实例,用来读取整个BeanFactory或ApplicationContext。

Bean依赖的决定通常取决于下面这些内容:

1.BeanFactory通过使用一个描述所有bean的配置被创建和实例化。

大多数的Spring用户使用一个支持XML格式配置文件的BeanFactory或ApplicationContext实现。

2.每一个bean的依赖表现为属性,构造函数参数,或者当用静态工厂方法代替普通构造函数时工厂方法的参数。

这些依赖将会在bean真正被创建出来后提供给bean。

3.每一个属性或者构造函数参数要么是一个要被设置的值的定义,要么是一个指向BeanFactory中其他bean的引用。

在ApplicationContext的情况下,这个引用可以指向一个父亲ApplicationContext中bean。

4.每一个属性或构造函数参数的值,必须能够从(配置文件中)被指定的格式转变为真实类型。

缺省情况下,Spring能够把一个字符串格式的值转变为所有内建的类型,比如int,long,String,boolean等等。

另外当说到基于XML的BeanFactory实现的时候(包括ApplicationContext实现),它们已经为定义Lists,Maps,Sets和Properties集合类型提供了内在的支持。

另外,Spring通过使用JavaBeans的PropertyEditor定义,能够将字符串值转变为其他任意的类型。

(你可以为PropertyEditor提供你自己的PropertyEditor定义从而能够转变你自定义的类型;更多关于PropertyEditors的信息以及如何手工增加自定义的PropertyEditors请参看第3.9节“注册附加的定制PropertyEditor”)。

当一个bean属性是一个JavaClass类型,Spring允许你用这个类的名字的字符串作为这个属性的值,ClassEditor这个内建的PropertyEditor会帮你把类的名字转变成真实的Class实例。

5.很重要的一点就是:

Spring在BeanFactory创建的时候要校验BeanFactory中每一个Bean的配置。

这些校验包括作为Bean引用的属性必须实际引用一个合法的bean(比如被引用的bean也定义在BeanFactory中,或者当ApplicationContext时,在父亲ApplicationContext中)。

但是,bean属性本身直到bean被真实建立的的时候才被设置。

对于那些是singleton并且被设置为pre-instantiated的bean来说(比如一个ApplicationContext中的singletonbean),bean在创建BeanFactory的时候创建,但是对于其他情况,发生在bean被请求的时候。

当一个bean必须被创建时,它会潜在地导致一系列的其他bean被创建,像它的依赖以及它的依赖的依赖(如此下去)被创建和赋值。

6.通常你可以信任Spring做了正确的事情。

它会在BeanFactory装载的时候检查出错误,包括对不存在bean的引用和循环引用。

它会尽可能晚地设置属性和解决依赖(比如创建那些需要的依赖),也就是在bean真正被创建的时候。

这就意味着:

就算一个BeanFactory被正确地装载,稍后当你请求一个bean的时候,如果创建那个bean或者它的依赖的时候出现了错误,这个BeanFactory也会抛出一个异常。

比如,如果一个bean抛出一个异常作为缺少或非法属性的结果,这样的情况就会发生。

这种潜在地推迟一些配置错误可见性的行为正是ApplicationContext默认预实例化singletonbean的原因。

以前期的时间和内存为代价在beans真正需要之前创建它们,你就可以在ApplicationContext创建的时候找出配置错误,而不是在后来。

如果你愿意,你也可以覆盖这种默认的行为,设置这些singletonbean为lazy-load(不是预实例化的)。

几个例子:

首先,一个使用BeanFactory以及基于setter方法的依赖注射。

下面是一个定义了一些bean的XmlBeanFactory配置文件的一小部分。

接下去是正式的bean的代码,演示了正确的setter方法声明。

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > IT计算机 > 计算机软件及应用

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1