Spring 定義:abstract="true" ,可適用模板

langgufu314發表於2013-07-22

Spring 定義:abstract="true"  

今天看到很多配置檔案中都有這樣的寫法:
<!-- 配置daoTemplate,作為所有DAO元件的模板 -->
<bean id="daoTemplate" abstract="true">
<!-- 為DAO元件注入SessionFactory引用 -->
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!-- 配置stateDao元件 -->
<bean id="stateDao" parent="daoTemplate"
class="org.crazyit.auction.dao.impl.StateDaoHibernate"/>
<!-- 配置kindDao元件 -->
<bean id="kindDao" parent="daoTemplate"
class="org.crazyit.auction.dao.impl.KindDaoHibernate"/>
 
為什麼<bean id="daoTemplate" abstract="true">裡面沒有指定class呢?我查了spring手冊,裡面的例子都是有class指向的,因為一個bean沒有class單獨存在肯定無意義 ,後面一般是子類的指向。因為一個子bean定義可以從父bean繼承構造器引數值、屬性值以及覆蓋父bean的方法,並且可以有選擇地增加新的值。
 
 
先看看下面這段話:

bean定義的繼承

在bean定義中包含了大量的配置資訊,其中包括容器相關的資訊(比如初始化方法、靜態工廠方法名等等)以及構造器引數和屬性值。子bean定義就是從父bean定義繼承配置資料的bean定義。它可以覆蓋父bean的一些值,或者新增一些它需要的值。使用父/子bean定義的形式可以節省很多的輸入工作。實際上,這就是一種模板形式。

當以程式設計的方式使用BeanFactory時,子bean定義用ChildBeanDefinition類表示。大多數使用者從來不需要以這個方式使用它們,而是以類似XmlBeanFactory中的宣告方式去配置bean定義。當使用基於XML的配置後設資料時,給'parent'屬性指定值,意味著子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>

如果子bean定義沒有指定class屬性,它將使用父bean定義的class屬性,當然也可以覆蓋它。在後面一種情況中,子bean的class屬性值必須同父bean相容,也就是說它必須接受父bean的屬性值。

一個子bean定義可以從父bean繼承構造器引數值、屬性值以及覆蓋父bean的方法,並且可以有選擇地增加新的值。如果指定了init-method,destroy-method和/或靜態factory-method,它們就會覆蓋父bean相應的設定。

剩餘的設定將總是從子bean定義處得到:依賴自動裝配模式依賴檢查singleton作用域延遲初始化

注意在上面的例子中,我們使用abstract屬性顯式地將父bean定義標記為抽象的。 下面是個父bean定義並沒有指定class屬性的例子,其中父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是不完整的,而且還被顯式標記為抽象的,因而它無法得到自己的例項。抽象bean定義可作為子bean定義的模板。若要嘗試單獨使用這樣的父bean(比如將它作為其他bean的ref屬性而引用,或者直接使用這個父bean的id作為引數呼叫getBean()方法),將會導致錯誤。同樣地,容器內部的preInstantiateSingletons()方法會完全忽略abstract的bean定義。

注意

預設情況下,ApplicationContext不是BeanFactory)會預例項化所有singleton的bean。因此很重要的一點是:如果你只想把一個(父)bean定義當作模板使用,而它又指定了class屬性,那麼你就得將'abstract'屬性設定為'true',否則應用上下文將會(試著)預例項化抽象bean。

 
如果你有一個(父)bean定義你希望僅僅作為模版使用,而這個定義說明了一個類,你必須把abstract引數設定為true,否則應用程式上下文將試圖預先初始化它。

相關文章