Bean 定義繼承
一個 Bean 定義可以包含大量配置資訊,包括建構函式引數、屬性值以及容器特定的資訊,例如初始化方法、靜態工廠方法名等等。子 Bean 定義繼承父定義的配置資料。子定義可以覆蓋某些值或根據需要新增其他值。使用父子 Bean 定義可以節省大量工作。實際上,這是一種模板化形式。
如果你以程式設計方式使用 ApplicationContext
介面,子 Bean 定義由 ChildBeanDefinition
類表示。大多數使用者不會在此級別上使用它們。相反,他們會在像 ClassPathXmlApplicationContext
這樣的類中以宣告方式配置 Bean 定義。當你使用基於 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"> (1)
<property name="name" value="override"/>
<!-- the age property value of 1 will be inherited from parent -->
</bean>
1 | 注意 parent 屬性。 |
如果未指定類,子 Bean 定義將使用父定義中的 Bean 類,但也可以覆蓋它。在後一種情況下,子 Bean 類必須與父類相容(即,它必須接受父類的屬性值)。
子 Bean 定義從父定義繼承作用域、建構函式引數值、屬性值和方法覆蓋,並且可以選擇新增新值。你指定的任何作用域、初始化方法、銷燬方法或 static
工廠方法設定都會覆蓋相應的父設定。
其餘設定始終取自子定義:depends-on、自動裝配模式、依賴檢查、singleton 和延遲初始化。
前面的示例透過使用 abstract
屬性將父 Bean 定義顯式標記為抽象。如果父定義未指定類,則必須顯式將父 Bean 定義標記為 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 屬性引用或使用父 Bean ID 進行顯式的 getBean()
呼叫)將返回錯誤。同樣,容器的內部 preInstantiateSingletons()
方法會忽略定義為抽象的 Bean 定義。
ApplicationContext 預設會預先例項化所有 singleton Bean。因此,重要的一點(至少對於 singleton Bean 來說)是,如果你有一個(父)Bean 定義僅打算用作模板,並且此定義指定了類,則必須確保將 abstract 屬性設定為 true,否則應用上下文將實際(嘗試)預先例項化該 abstract Bean。 |