Bean Definition Inheritance

一个 bean 定义可能包含大量的配置信息,包括构造函数参数、属性值,以及与容器相关的特定信息,例如,初始化方法、静态工厂方法名等等。子 bean 定义继承了一个父定义的配置数据。子定义可以根据需要覆盖一些值或添加另一些值。使用父 bean 定义和子 bean 定义可以节省大量的重复输入。事实上,这是一种模板化的形式。

A bean definition can contain a lot of configuration information, including constructor arguments, property values, and container-specific information, such as the initialization method, a static factory method name, and so on. A child bean definition inherits configuration data from a parent definition. The child definition can override some values or add others as needed. Using parent and child bean definitions can save a lot of typing. Effectively, this is a form of templating.

如果您在编程中使用 ApplicationContext 接口,则子 bean 定义将由 ChildBeanDefinition 类表示。大多数用户不会在此级别使用它们。反之,它们会在诸如 ClassPathXmlApplicationContext 的类中以声明方式配置 bean 定义。当使用基于 XML 的配置元数据时,您可以通过使用 parent 属性注明子 bean 定义,将父 bean 指定为该属性的值。以下示例展示了如何执行此操作:

If you work with an ApplicationContext interface programmatically, child bean definitions are represented by the ChildBeanDefinition class. Most users do not work with them on this level. Instead, they configure bean definitions declaratively in a class such as the ClassPathXmlApplicationContext. When you use XML-based configuration metadata, you can indicate a child bean definition by using the parent attribute, specifying the parent bean as the value of this attribute. The following example shows how to do so:

<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">  1
	<property name="name" value="override"/>
	<!-- the age property value of 1 will be inherited from parent -->
</bean>
1 Note the parent attribute.

如果未指定子 bean 定义,它将使用父定义中的 bean 类,但也能够覆盖它。在后一种情况下,子 bean 类必须与父类兼容(即,它必须接受父类的属性值)。

A child bean definition uses the bean class from the parent definition if none is specified but can also override it. In the latter case, the child bean class must be compatible with the parent (that is, it must accept the parent’s property values).

子 bean 定义从父类继承范围、构造函数参数值、属性值和方法覆盖,同时可以选择添加新值。您指定的任何范围、初始化方法、销毁方法或静态工厂方法设置都将覆盖相应的父级设置。

A child bean definition inherits scope, constructor argument values, property values, and method overrides from the parent, with the option to add new values. Any scope, initialization method, destroy method, or static factory method settings that you specify override the corresponding parent settings.

其他设置始终从子定义中获取:依赖、自动连线模式、依赖检查、单例和延迟初始化。

The remaining settings are always taken from the child definition: depends on, autowire mode, dependency check, singleton, and lazy init.

前一个示例通过使用 abstract 属性明确将父 bean 定义标记为抽象属性。如果父定义未指定类,则需要明确将父 bean 定义标记为 abstract,如下例所示:

The preceding example explicitly marks the parent bean definition as abstract by using the abstract attribute. If the parent definition does not specify a class, explicitly marking the parent bean definition as abstract is required, as the following example shows:

<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 定义,该定义用作子定义的父定义。尝试通过将其作为另一个 bean 的 ref 属性引用的方式或通过使用父 bean ID 执行显式的 getBean() 调用来单独使用此类 abstract 的父 bean,将返回一个错误。同样地,容器的内部 preInstantiateSingletons() 方法将忽略被定义为 abstract 的 bean 定义。

The parent bean cannot be instantiated on its own because it is incomplete, and it is also explicitly marked as abstract. When a definition is abstract, it is usable only as a pure template bean definition that serves as a parent definition for child definitions. Trying to use such an abstract parent bean on its own, by referring to it as a ref property of another bean or doing an explicit getBean() call with the parent bean ID returns an error. Similarly, the container’s internal preInstantiateSingletons() method ignores bean definitions that are defined as abstract.

ApplicationContext 在默认情况下预实例化所有单例。因此,(至少对于单例 bean),如果你有一个仅打算用作模板的(父)bean 定义,并且此定义指定了一个类,则必须确保将 abstract 属性设置为 true,否则应用程序上下文实际上将(尝试)预实例化 abstract bean。

ApplicationContext pre-instantiates all singletons by default. Therefore, it is important (at least for singleton beans) that if you have a (parent) bean definition which you intend to use only as a template, and this definition specifies a class, you must make sure to set the abstract attribute to true, otherwise the application context will actually (attempt to) pre-instantiate the abstract bean.