Bean定義可以包含許多配置信息,包括構造函數參數,屬性值和特定於容器的信息,例如初始化方法,靜態工廠方法名稱等。子bean定義從父定義繼承配置數據。子定義可以覆蓋某些值或根據需要添加其他值。使用父bean和子bean定義可以節省很多輸入。實際上,這是一種模板形式。
如果您以編程方式使用ApplicationContext接口,則子bean定義由ChildBeanDefinition類表示。大多數用戶不在此級別上與他們合作。相反,它們在諸如ClassPathXmlApplicationContext之類的類中聲明性地配置Bean定義。當使用基於XML的配置元數據時,可以通過使用父屬性來指示子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"> <property name="name" value="override"/> <!-- the age property value of 1 will be inherited from parent --> </bean>
Note the parent
attribute.
如果未指定子bean定義,則使用父定義中的bean類,但也可以覆蓋它。 在後一種情況下,子bean類必須與父類兼容(也就是說,它必須接受父類的屬性值)。
子bean定義從父對象繼承範圍,構造函數參數值,屬性值和方法替代,並可以選擇添加新值。 您指定的任何範圍,初始化方法,destroy方法或靜態工廠方法設置都會覆蓋相應的父設置。
其餘設置始終從子定義中獲取:依賴項,自動裝配模式,依賴項檢查,單例和惰性初始化。
前面的示例使用abstract屬性將父bean定義顯式標記爲abstract。 如果父定義未指定類,則需要將父bean定義顯式標記爲抽象,如以下示例所示:
<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不能單獨實例化,因爲它不完整,並且還被明確標記爲抽象。 當定義是抽象的時,它只能用作純模板bean定義,用作子定義的父定義。 通過將其稱爲另一個bean的ref屬性或使用父bean ID進行顯式getBean()調用來嘗試單獨使用這樣的抽象父bean會返回錯誤。 同樣,容器的內部preInstantiateSingletons()方法將忽略定義爲抽象的bean定義。
默認情況下,ApplicationContext會預先實例化所有單例。 因此,重要的是(至少對於單例bean),如果有一個(父)bean定義僅打算用作模板,並且此定義指定了一個類,則必須確保將abstract屬性設置爲true ,否則應用程序上下文將實際上(試圖)預先實例化抽象bean。