IOC BeanFactory XML之旅

本文深入剖析了Spring的XML配置文件,详细讲解了beans和bean元素,包括description、import、alias、bean的id、class属性以及构造方法和setter方法的注入方式。同时,介绍了property、Constructor-arg中的配置项,如Value、ref、idref等,并探讨了bean的scope、工厂方法与FactoryBean的使用,以及方法注入和方法替换的概念,展示了Spring IoC容器的强大功能。
摘要由CSDN通过智能技术生成

目录

beans和bean

 beans之唯我独尊

description、import和alias

description

 import

alias

bean

id属性

class属性

bean的具体属性及里面的内容

构造方法注入的XML之道

type属性

index属性

setter方法注入的XML之道

property和Constructor-arg中可用的配置项

Value

ref

idref

内部bean

 list

Set

map

props

null

depends-on

autowire

no

byName

byType

Constructor

autodetect

手动绑定与自动绑定

dependency-check

lazy-init

bean的继承

bean的scope

singleton

prototype

request、session和global session

自定义scope类型

工厂方法与FactoryBean

静态工厂方法 Static Factory Method)

非静态工厂方法(Instance Factory Method)

FactoryBean

bean的方法替换与prototype得到最新对象

方法注入

使用BeanFactoryAware接口

使用ObjectFactoryCreatingFactoryBean

方法替换


XML格式的容器信息管理方式是Spring提供的最为强大、支待最为全面的方式。从Spring的参考 文档到各Spring相关书籍,都是按照XML的配置进行说明的,这部分内容可以让你充分领略到Spring 的IoC容器的魅力,以致于我们也不得不带你初次或者再次踏上Spring的XML之旅。

beans和bean

所有使用XML文件进行配置信息加载的Spring IoC容器,包括BeanFactory和 ApplicationContext的所有XML相应实现,都使用统一的XML格式。

在Spring 2.0版本之前,这种格 式由Spring提供的DTD规定,也就是说,所有的Spring容器加载的XML配置文件的头部,都需要以下 形式的DOCTYPE声明:

从Spring 2.0版本之后,Spring在继续保持向前兼容的前提下,既可以继续使用DTD方式的DOCTYPE 进行配置文件格式的限定,又引入了基于XML Schema的文档声明。所以,Spring 2.0之后,同样可以 使用代码清单所展示的基于XSD的文档声明。

不过,不管使用哪一种形式的文档声明,实际上限定的元素基本上是相同的。让我们从最顶层的 元素开始,看一下这两种文档声明都限定了哪些元素吧!

所有注册到容器的业务对象,在Spring中称之为Bean。所以,每一个对象在XML中的映射也自然 而然地对应一个叫做<bean>的元素。既然容器最终可以管理所有的业务对象,那么在XML中把这些 叫做<bean>的元素组织起来的,就叫做<beans>。多个<bean>组成一个<beans>很容易理解,不是吗?

 beans之唯我独尊

<beans>是XML配置文件中最顶层的元素,它下面可以包含0或者1个<description>和多个 <bean>以及<import>或者<alias>, 如图所示。

<beans>作为所有<bean>的“统帅",它拥有相应的属性(attribute)对所辖的<bean>进行统一 的默认行为设置,包括如下几个。

Default-lazy-init。其值可以指定为true或者false, 默认值为false。用来标志是否对所 有的<bean>进行延迟初始化。

Default-autowire。可以取值为no、byName、byType、Constructor以及autodetect。默 认值为no, 如果使用自动绑定的话,用来标志全体bean使用哪一种默认绑定方式。

Default-dependency-check。可以取值none、objects、simple以及all, 默认值为none, 即不做依赖检查。

Default-init-method。如果所管辖的<bean>按照某种规则,都有同样名称的初始化方法的 话,可以在这里统一指定这个初始化方法名,而不用在每一个<bean>上都重复单独指定。

Default-destiroy-method。与Default-init-method相对应,如果所管辖的bean有按照某种 规则使用了相同名称的对象销毁方法,可以通过这个属性统一指定。

description、import和alias

之所以把这几个元素放到一起讲解,是因为通常情况下它们不是必需的。不过,了解一下也没什 么不好,不是吗?

description

可以通过<description>在配置的文件中指定一些描述性的信息。通常情况下,该元素是省略的。

当然,如果愿意,<description>随时可以为我们效劳。

 import

通常情况下,可以根据模块功能或者层次关系,将配置信息分门别类地放到多个配置文件中。在 想加载主要配置文件,并将主要配置文件所依赖的配置文件同时加载时,可以在这个主要的配置文件 中通过<import>元素对其所依赖的配置文件进行引用。比如,如果A.xml中的<bean:>定义可能依赖 B.xml中的某些<bean>定义,那么就可以在A.xml中使用<import>将B.xml引入到A.xml, 以类似于 <import resource="B.xml"户的形式。

但是,这个功能在我看来价值不大,因为容器实际上可以同时加载多个配置,没有必要非通过一 个配置文件来加载所有配置。不过,或许在有些场景中使用这种方式比较方便也说不定。

alias

可以通过<alias>为某些<bean>起一些“外号” (别名),通常情况下是为了减少输入。比如, 假设有个<bean>, 它的名称为dataSourceForMasterDatabase, 你可以为其添加一个<alias>, 像这样 <alias name="dataSourceForMasterDatabase" alias="masterDataSource"/>。以后通过 dataSourceForMasterDatabase或者masterDataSource来引用这个<bean>都可以,只要你觉得方便 就行。

bean

哦,错了,是孤孤单单一个Bean。每个业务对象作为个体,在Spring的XML配置文件中是与<bean> 元素一一对应的。窥一斑而知全豹,只要我们了解单个的业务对象是如何配置的,剩下的就可以“依 葫芦画飘”了。所以,让我们先从最简单的单一对象配置开始吧!如下代码演示了最基础的对象配置 形式:

<bean id="djNewsListener" class=" .. impl.DowJonesNewsListener"> </bean>

id属性

通常,每个注册到容器的对象都需要一个唯一标志来将其与“同处一室”的"兄弟们“区分开来, 就好像我们每一个人都有一个身份证号一样(重号的话就比较麻烦)。通过过属性来指定当前注册对 象的beanName是什么。这里,通过指定beanName为djNewsListener。实际上,并非任何情况下都 需要指定每个<bean>的id,有些情况下,id可以省略,比如后面会提到的内部<bean>以及不需要根据 beanName明确依赖关系的场合等。

除了可以使用id来指定<bean>在容器中的标志,还可以使用name属性来指定<bean>的别名 (alias)。比如,以上定义,我们还可以像如下代码这样,为其添加别名:

<bean id="djNewsListener"  name="/news/djNewsListener,dowJonesNewsListener" class=" .. impl.DowJonesNewsListener">

</bean>

与id属性相比,name属性的灵活之处在于,name可以使用id不能使用的一些字符,比如/。而且 还可以通过逗号、空格或者冒号分割指定多个name。

name的作用跟使用<alias>为id指定多个别名基 本相同:

<alias name="djNewsListener" alias="/news/ctjNewsListener"/> <alias name="ctjNewsListener" alias="ctowJonesNewsListener"/>

class属性

每个注册到容器的对象都需要通过<bean>元素的class属性指定其类型,否则,容器可不知道这 个对象到底是何方神圣。在大部分情况下,该属性是必须的。仅在少数情况下不需要指定,如后面将 提到的在使用抽象配置模板的情况下。

bean的具体属性及里面的内容

在大部分情况下,你不太可能选择单独”作战”,业务对象也是;各个业务对象之间会相互协作 来更好地完成同一使命。这时,各个业务对象之间的相互依赖就是无法避免的。对象之间需要相互协 作,在横向上它们存在一定的依赖性。而现在我们就是要看一下,在Spring的IoC容器的XML配置中, 应该如何表达这种依赖性。

既然业务对象现在都符合IoC的规则,那么要了解的表达方式其实也很简单,无非就是看一下构 造方法注入和setter方法注入通过XML是如何表达的而已。那么,让我们开始吧!

构造方法注入的XML之道

按照Spring的IoC容器配置格式,要通过构造方法注入方式,为当前业务对象注入其所依赖的对象, 需要使用<Constuctor-arg>。正常情况下,如以下代码所示:

对于<ref>元素,稍后会进行详细说明。这里你只需要知道,通过这个元素来指明容器将为 djNewsProvider这个<bean>注入通过<ref>所引用的Bean实例。这种方式可能看起来或者编写起来 不是很简洁,最新版本的Spring也支持配置简写形式,如以下代码所示:

简洁多了不是嘛?其实,无非就是表达方式不同而已,实际达到的效果是一样的。

有些时候,容器在加载XML配置的时候,因为某些原因,无法明确配置项与对象的构造方法参数 列表的一一对应关系,就需要请<constructor-arg>的type或者index属性出马。比如,对象存在多 个构造方法,当参数列表数目相同而类型不同的时候,容器无法区分应该使用哪个构造方法来实例化 对象,或者构造方法可能同时传入最少两个类型相同的对象

type属性

假设有一个对象定义如代码清单

该类声明了两个构造方法,分别都只是传入一个参数,且参数类型不同。这时,我们可以进行配 置,如以下代码所示:

如果从BeanFactory取得该对象并调用toString()查看的话,我们会发现Spring调用的是第一个 构造方法,因为输出是如下内容:

但是,如果我们想调用的却是第二个传入int类型参数的构造方法,又该如何呢?可以使用type属 性,通过指定构造方法的参数类型来解决这一问题,配置内容如下代码所示:

index属性

当某个业务对象的构造方法同时传入了多个类型相同的参数时,Spring又该如何将这些配置中的 信息与实际对象的参数一一对应呢?好在,如果配置项信息和对象参数可以按照顺序初步对应的话,Spring还是可以正常工作的

但是,如果要让"11111"作为对象的第二个参数,而将"22222"作为第一个参数来构造对象, 又该如何呢?好!可以颠倒配置项

setter方法注入的XML之道

与构造方法注入可以使用<Constructor-arg>注入配置相对应,Spring为setter方法注入提供了 <property>元素。

<property>有一个name属性(attribute) , 用来指定该<property>将会注入的对象所对应的实例变量名称。之后通过value或者ref属性或者内嵌的其他元素来指定具体的依赖对象引用或者值,如以 下代码所示:

 

当然,如果只是使用<property>进行依赖注入的话,请确保你的对象提供了默认的构造方法, 也就是一个参数都没有的那个。

以上配置形式还可以简化为如下形式:

使用<property>的setter方法注入和使用<Constructor-arg>的构造方法注入并不是水火不容 的。实际上,如果需要,可以同时使用这两个元素:

当然,现在需要MockBusinessObject提供一个只有一个String类型参数的构造方法,并且为 dependency2提供了相应的setter方法。代码清单演示了符合条件的一个业务对象定义。

property和Constructor-arg中可用的配置项

之前我们看到,可以通过在<property>和<Constructor-arg>这两个元素内部嵌套<Value>或者 <ref>, 来指定将为当前对象注入的简单数据类型或者某个对象的引用。不过,为了能够指定多种注 入类型,Spring还提供了其他的元素供我们使用,这包括bean、ref、idref、value、null、list、set、map、 props。下面我们来逐个详细讲述它们。

提示 以下涉及的所有内嵌元素,对于<property>和<constructor-arg>都是通用的。

Value

可以通过value为主体对象注入简单的数据类型,不但可以指定String类型的数据, 而且可以指定其他Java语言中的原始类型以及它们的包装器(wrapper)类型,比如int,integer等。 容器在注入的时候,会做适当的转换工作(我们会在后面揭示转换的奥秘)。你之前已经见过如何使 用<value>了,不过让我们通过如下代码来重新认识一下它:

当然,如果愿意,你也可以使用如下的简化形式(不过这里的value是以上一层元素的属性身份 出现):

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值