在spring中,两个最基本最重要的包是 org.springframework.beans 与 org.springframework.context. 这两个包中的代码为spring的反向控制 特性(也叫作依赖注射)提供了基础. beanfactory提供了一种先进的配置机制来管理任何种类bean(对象),这种配置机制考虑到任何一种可能的存储方式. applicationcontext建立在beanfactory之上,并增加了其他的功能,比如更容易同spring aop特性整合, 消息资源处理(用于国际化),事件传递,以声明的方式创建applicationcontext, 可选的父上下文与与应用层相关的上下文(比如webapplicationcontext),以及其他方面的增强. 【程序编程相关:Java数据结构---基于数组的表】
3.1. 简介 【推荐阅读:in Software that use】用户有时不能确定beanfactory与applicationcontext中哪一个在特定场合下更适合. 通常大部分在j2ee环境的应用中,最好选择使用applicationcontext, 因为它不仅提供了beanfactory所有的特性以及它自己附加的特性,而且还提供以声明的方式使用一些功能, 这通常是令人满意的.beanfactory主要是在非常关注内存使用的情况下 (比如在一个每kb都要计算的applet中)使用,而且你也不需要用到applicationcontext的所有特性. 【扩展信息:Eclipse3.0+Tomcat5.0】
简而言之,beanfactory提供了配置框架与基本的功能, 而 applicationcontext为它增加了更强的功能,这些功能中的一些或许更加接近j2ee并且围绕企业级应用.一般来说,applicationcontext是beanfactory的完全超集, 任何beanfactory功能与行为的描述也同样被认为适用于applicationcontext
这一章粗略地分为两部分,第一部分包括对beanfactory与applicationcontext都适用的一些基本原则.第二部分包括仅仅适用于applicationcontext的一些特性
3.2. beanfactory 与 beandefinitions - 基础3.2.1. beanfactorybeanfactory实际上是实例化,配置与管理众多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:
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层提供支持代码,在j2ee web应用启动过程中自动载入一个spring applicationcontext.这个声明过程在这里描述:
编程操作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>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你可以像下面这样定义你的bean class:
<bean id="examplebean" class="examples.examplebean"/> <bean name="anotherexample" class="examples.examplebeantwo"/>至于为构造函数提供(可选的)参数,以及对象实例创建后设置实例属性,将会在后面叙述
3.2.3.2. 通过静态工厂方法创建bean当你定义一个使用静态工厂方法创建的bean,同时使用class属性指定包含静态工厂方法的类,这个时候需要factory-method属性来指定工厂方法名.spring调用这个方法(包含一组可选的参数)并返回一个有效的对象,之后这个对象就完全与构造方法创建的对象一样.用户可以使用这样的bean定义在遗留代码中调用静态工厂.
下面是一个bean定义的例子,声明这个bean要通过factory-method指定的方法创建.注意这个bean定义并没有指定返回对象的类型,只指定包含工厂方法的类.在这个例子中,createinstance 必须是static方法 .
<bean id="examplebean" class="examples.examplebean2" factory-method="createinstance"/>至于为工厂方法提供(可选的)参数,以及对象实例被工厂方法创建后设置实例属性,将会在后面叙述.
3.2.3.3. 通过实例工厂方法创建bean使用一个实例工厂方法(非静态的)创建bean与使用静态工厂方法非常类似,调用一个已存在的bean(这个bean应该是工厂类型)的工厂方法来创建新的bean.
使用这种机制,class属性必须为空,而且factory-bean属性必须指定一个bean的名字,这个bean一定要在当前的bean工厂或者父bean工厂中,并包含工厂方法. 而工厂方法本身仍然要通过factory-method属性设置.
下面是一个例子:
<!-- the factory bean, which contains a method called createinstance --> <bean id="myfactorybean" class="..."> ... </bean> <!-- the bean to be created via the factory bean --> <bean id="examplebean" 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,并且它在xml dtd(定义文档)中作为一个真正的xml元素的id属性被标记, 所以xml解析器能够在其他元素指回向它的时候做一些额外的校验.正因如此,用id属性指定bean的id是一个比较好的方式. 然而,xml规范严格限定了在xml id中合法的字符.通常这并不是真正限制你, 但是如果你有必要使用这些字符(在id中的非法字符),或者你想给bean增加其他的别名, 那么你可以通过name属性指定一个或多个id(用逗号,或者分号;分隔).
3.2.5. singleton的使用与否beans被定义为两种部署模式中的一种:singleton或non-singleton. (后一种也别叫作prototype,尽管这个名词用的不精确因为它并不是非常适合). 如果一个bean是singleton形态的,那么就只有一个共享的实例存在, 所有与这个bean定义的id符合的bean请求都会返回这个唯一的.特定的实例.
如果bean以non-singleton,prototype模式部署的话,对这个bean的每次请求都会创建一个新的bean实例.... 下一页