BeanFactory中的每个bean都必须至少有一个唯一的名字,Spring为了灵活的支持各种情形,使用了相对复杂的命名体系。如果我们为bean指定了id属性,那么id属性的值将成为bean的名称,如果没有指定id属性,Spring将使用name属性的第一个值(多个值用逗号或者分号分隔)作为bean的名称,如果name属性也没有指定,Spring将使用bean的类名(包括package的完整类名)来作为bean的名称,对于多个bean使用相同类名的情况,Spring会在类名后面添加#2,#3等序号来加以区别。不管怎么说,使用id属性来指定bean的名称总是一个不错的选择。
在Spring中,所有bean默认都是以单例(singleton)形态存在的,也就是说我们通过BeanFactory的getBean方法获取的同一名称的bean是完全相同的,即:beanFactory.getBean("name")==beanFactory.getBean("name")。更改bean的形态为非singleton(原型的,prototype)是很容易的,只需在bean标签中,指定singleton属性为false就可以了。
<bean id="nonSingleton" class="java.lang.String" singleton="false">
...
</bean>
为了简化配置,Spring还提供了自动组装(Auto-Wiring)bean的功能,有四种自动组装方式:根据名称(byName),根据类型(byType),构造子(Constructor)以及自动侦测(autodetect)。
使用根据名称自动组装时,Spring根据bean的属性的名称去寻找同名的bean配置。
使用根据类型自动组装时,Spring根据bean的属性的类型去寻找同类型的bean配置,如果有多个同类型的bean配置,那么Spring将会抛出异常,以表示无法确定使用哪个。
使用构造子自动组装和使用根据类型自动组装比较类似,需要注意的是,使用构造子自动组装时,Spring会匹配尽可能多的参数。例如,我们有一个bean拥有两个构造函数,第一个接收一个String类型的参数,第二个接收一个String类型和一个Integer类型的参数,这时,如果在beanFactory的配置文件中有一个String类型的bean配置和一个Integer类型的bean配置,那么Spring将会使用第二个拥有两个参数的构造函数。
使用自动侦测组装时,Spring会在根据类型自动组装和根据构造子自动组装之间自动作出选择,依据是:如果bean拥有默认的(无参数的)构造函数,那么Spring使用根据类型自动组装的方式,否则,使用根据构造子自动组装的方式。
有时候,我们可能会有多个bean拥有共同的类型,或是实现一些共同的接口,因此它们会有一些相同的配置,如果能将这些相同的配置提取出来,各个bean只要继承这些相同的配置,然后添加自己特有的配置,将会大大减少重复的配置,降低发生错误的可能。Spring的bean继承机制就是出于这样的目的而提供的。在Spring中,我们可以将这些相同的配置提取出来,配置成一个parent bean,然后各个bean(child bean)可以继承parent bean,在child bean中,可以覆写parent bean中的配置,也可以添加自己的配置。parent bean是通过child bean的bean标签的parent属性来指定的。
<bean id="inheritParent" class="com.apress.prospring.ch4.inheritance.SimpleBean">
<property name="name">
<value>Rob Harrop</value>
</property>
<property name="age">
<value>22</value>
</property>
</bean>
<bean id="inheritChild" class="com.apress.prospring.ch4.inheritance.SimpleBean"
parent="inheritParent">
<property name="age">
<value>35</value>
</property>
</bean>
需要注意的是,bean的继承体系并不完全等同于java的类继承体系,我们完全可以在数个拥有相同类型的bean上使用继承,这不会带来任何问题。因此,相对于java的继承体系来说,Spring 的bean继承体系更类似于模板类型。