Bean 定義繼承
一個 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、自動裝配模式、依賴檢查、單例和延遲初始化。
前面的示例使用 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 預設預例項化所有單例。因此,重要的是(至少對於單例 bean 而言),如果您有一個(父)bean 定義,並且您打算僅將其用作模板,並且此定義指定了一個類,則您必須確保將 abstract 屬性設定為 true,否則應用程式上下文將實際(嘗試)預例項化 abstract bean。 |