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 定義從父 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。因此,重要的是(至少對於 singleton Bean 而言),如果您有一個(父)Bean 定義,您僅打算將其用作範本,並且此定義指定了一個類別,則必須確保將 abstract 屬性設定為 true,否則應用程式 Context 實際上會(嘗試)預先實例化 abstract Bean。 |