Spring bean定义继承

一个bean定义包含了大量的配置信息,包含了构造器参数,属性值,和容器指定的信息,比如初始化方法,静态工厂方法名,等等。子bean从父bean那里继承配置数据。子定义可以重写一些值,或者按需添加别的值。使用子和父beans定义可以节约大量的输入。这就是使用模板的高效。

如果你使用ApplicationContext接口程序化编程,子bean定义由ChildBeanDefinition类表示。大多数使用者不会在这个级别使用它们,而是配置bean定义声明,比如ClassPathXmlApplicationContext。当你使用基于XML配置元数据时,你使用parent属性指定一个子bean定义,指定父bean作为这个属性的值。

<bean id="inheritedTestBean" abstract="true"
    class="org.springframework.beans.TestBean">
  <property name="name" value="parent"/>
  <property name="age" value="1"/>
</bean>

<bean id="inheritsWithDifferentClass"
      class="org.springframework.beans.DerivedTestBean"
      parent="inheritedTestBean" init-method="initialize">

  <property name="name" value="override"/>
  <!-- the age property value of 1 will be inherited from  parent -->

</bean>

一个子bean定义使用了来自父bean定义的bean类。如果没有指定,但也可以重写。在后面的案例中,子bean类必须与父bean类是兼容的,即,其必须接受父类的属性值。

一个子bean定义从其父bean中继承了构造器参数值,属性值,和方法重写,其还可以添加新的值。燃和初始化方法,销毁方法,并且/或者静态工厂方法设置将重写对应的父bean的设置。

剩下的设置总是从子定义中获取:depends on,autowire mode,依赖检查,singleton,scope,延迟加载。

前面的例子明确指定了父bean为abstract类型,其通过属性abstrat指定。如果父定义没有指定一个类,明确指定其为abstract是必须的。

<bean id="inheritedTestBeanWithoutClass" abstract="true">
    <property name="name" value="parent"/>
    <property name="age" value="1"/>
</bean>

<bean id="inheritsWithClass" class="org.springframework.beans.DerivedTestBean"
    parent="inheritedTestBeanWithoutClass" init-method="initialize">
  <property name="name" value="override"/>
  <!-- age will inherit the value of 1 from the parent bean definition-->
</bean>

父bean不能自己实例化,因为它完成不了,并且它也标识为abstract。当一个定义是abstract,其仅仅是一个纯净的模板bean定义,专门为子定义服务。使用这个abstract bean定义,通过作为另一个bean的ref属性关联它或者调用getBean()还有父bean的id关联它,将返回错误。相似地,容器内部的preInstantiateSingletons()方法忽视了bean定义(其如abstract定义一样)。

注意:ApplicationContext 默认的预处理实例化所有的singletons。因此这是很重要的(至少对于singleton beans),如果你想使用一个父bean作为一个模板,并且这个定义指定了一个类,你必须确保abstract属性值为true,否则应用上下文将真的会预处理实例化这个abstract bean。