Bean Definitions Inheritance

Herencia de definiciones de beans

⚠️ Baja importancia: toda la documentación de esta página trata sobre configuración XML.

Una definición de bean puede contener mucha información de configuración, incluidos argumentos de constructor, valores de propiedades e información específica del contenedor, como el método de inicialización o el nombre de un método de fábrica estático.

Una definición de bean hija hereda datos de configuración de una definición padre. La definición hija puede sobrescribir algunos valores o añadir otros según sea necesario. El uso de definiciones de beans padre e hija puede ahorrar bastante escritura. En la práctica, es una forma de usar plantillas.

Si trabajas mediante programación con la interfaz ApplicationContext, las definiciones de beans hijas se representan mediante la clase ChildBeanDefinition. Sin embargo, la mayoría de usuarios no trabaja en ese nivel. En su lugar, configura las definiciones de beans de forma declarativa, por ejemplo, con ClassPathXmlApplicationContext.

Cuando utilizas metadatos de configuración basados en XML, puedes indicar una definición de bean hija mediante el atributo parent, especificando como valor de dicho atributo el bean padre.

El siguiente ejemplo muestra cómo hacerlo:

<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"/>
	<!-- El valor 1 de la propiedad age se hereda del padre. -->
</bean>

Observa el atributo parent.

Una definición de bean hija utiliza la clase de bean de la definición padre cuando no se especifica otra. No obstante, también puede sobrescribirla. En este último caso, la clase del bean hijo debe ser compatible con la del padre; es decir, debe aceptar los valores de propiedades del padre.

Una definición de bean hija hereda del padre los siguientes elementos, con la posibilidad de añadir valores nuevos:

  • El ámbito.
  • Los valores de los argumentos del constructor.
  • Los valores de propiedades.
  • Las sustituciones de métodos.

Cualquier configuración de ámbito, método de inicialización, método de destrucción o método de fábrica static que especifiques en la definición hija sobrescribe la configuración correspondiente del padre.

Las siguientes configuraciones siempre se toman de la definición hija:

  • depends-on.
  • El modo de autoconexión.
  • La comprobación de dependencias.
  • El valor singleton.
  • La inicialización diferida.

El ejemplo anterior marca explícitamente la definición del bean padre como abstracta mediante el atributo abstract.

Si la definición padre no especifica una clase, es obligatorio marcarla explícitamente como abstract, como muestra el siguiente ejemplo:

<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 heredará el valor 1 de la definición del bean padre. -->
</bean>

El bean padre no puede instanciarse por sí mismo porque está incompleto y, además, se ha marcado explícitamente como abstract.

Cuando una definición es abstract, solo puede utilizarse como una definición de bean de plantilla que sirve de padre para definiciones hijas. Intentar utilizar ese bean padre abstracto por sí solo, ya sea refiriéndolo como propiedad ref de otro bean o realizando una llamada explícita a getBean() con el identificador del bean padre, produce un error.

De forma similar, el método interno preInstantiateSingletons() del contenedor ignora las definiciones de beans marcadas como abstractas.

De forma predeterminada, ApplicationContext preinstancia todos los beans singleton. Por tanto, al menos para los beans singleton, si tienes una definición de bean padre que pretendes utilizar únicamente como plantilla y dicha definición especifica una clase, debes asegurarte de establecer el atributo abstract en true. De lo contrario, el contexto de la aplicación intentará preinstanciar el bean abstracto.