2011-05-01 304 views
28

我們可以爲XML中提及的同一個bean id重複名稱嗎? 如果不是,那麼我們如何重寫Spring中的bean?Spring的覆蓋bean

+0

你能張貼一些示例xml以準確顯示你的意思 – 2011-05-01 15:20:22

回答

50

任何給定的Spring上下文對於任何給定的id或名稱只能有一個bean。在XML id屬性的情況下,這由模式驗證強制執行。在name屬性的情況下,這是由Spring的邏輯強制執行的。

但是,如果上下文是由兩個不同的XML描述符文件構成的,並且兩個文件都使用了id,則會「覆蓋」另一個文件。確切的行爲取決於文件在被上下文加載時的排序。

所以雖然有可能,但並不推薦。這很容易出錯並且很脆弱,如果你改變了一個而不是另一個的ID,你將不會從Spring那裏得到任何幫助。

+0

如果它們處於相同的層次結構中有風險,但可以使用'profiles'(請參閱我的回答)更好地控制它。 – 2015-05-07 11:42:25

+1

有沒有辦法指示Spring在遇到任何具有相同ID的bean(即強調不允許覆蓋)時拋出錯誤?這是用於'ServletContextHandler'的'contextConfigLocation'屬性。 – 2015-08-28 20:22:30

7

official spring manual一個例子:

<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> 

是你在找什麼?

+0

看起來像官方的春季手冊鏈接已損壞。 – Buchi 2012-02-01 10:11:50

+0

@Buchi感謝您的提示,修復了鏈接 – 2012-02-07 15:02:12

0

我們是否可以在其他xml中爲其他參考e.x聲明相同的bean id。

Servlet的Initialize.xml

<bean id="inheritedTestBean" class="org.springframework.beans.TestBean"> 
    <property name="name" value="parent"/> 
    <property name="age" value="1"/> 
</bean> 

其它XML(document.xml中)

<bean id="inheritedTestBean" class="org.springframework.beans.Document"> 
    <property name="name" value="document"/> 
    <property name="age" value="1"/> 
</bean> 
+0

春季是否允許?對不起,但我不清楚。 – Buchi 2012-02-01 10:07:41

+6

@Buchi是的,它是允許的。來自稍後順序讀取的文件中的Bean將完全覆蓋先前的定義,該定義完全不會被實例化。 – mrembisz 2012-02-21 14:14:44

+0

你確定嗎?你確定Spring在掃描結束時初始化/運行bean的構造函數嗎?所以當我們將'inheritedtTestBean'注入另一個實施將被注入的bean?第一還是第二? – RMachnik 2014-07-24 21:32:31

10

我會補充一點,如果你需要的只是覆蓋由您使用Bean的屬性,標識辦法也像skaffman解釋:

在你的第一個被調用的XML配置文件中:

<bean id="myBeanId" class="com.blabla"> 
     <property name="myList" ref="myList"/> 
    </bean> 

    <util:list id="myList"> 
     <value>3</value> 
     <value>4</value> 
    </util:list> 

在你的第二個所謂的XML配置文件:

<util:list id="myList"> 
     <value>6</value> 
    </util:list> 

然後你豆「myBeanId」將是6

5

不知道一個元素的「myList中」屬性被實例化,如果這正是你需要什麼,但我們使用配置文件來定義我們是在和每個環境的具體豆運行的環境,所以它的類似的東西:

<bean name="myBean" class="myClass"> 
    <constructor-arg name="name" value="originalValue" /> 
</bean> 
<beans profile="DEV, default"> 
    <!-- Specific DEV configurations, also default if no profile defined --> 
    <bean name="myBean" class="myClass"> 
     <constructor-arg name="name" value="overrideValue" /> 
    </bean> 
</beans> 
<beans profile="CI, UAT"> 
    <!-- Specific CI/UAT configurations --> 
</beans> 
<beans profile="PROD"> 
    <!-- Specific PROD configurations --> 
</beans> 

因此,在這種情況下,如果I D不定義配置文件,或者如果我將其定義爲「DEV」,則myBean將爲其名稱參數獲得「overrideValue」。但是,如果我將配置文件設置爲「CI」,「UAT」或「PROD」,它將獲得「originalValue」作爲值。

0

其他職位沒有提到的另一個好方法是使用PropertyOverrideConfigurer如果你只是想覆蓋性能一些豆類。

例如,如果您想覆蓋測試的數據源(即,使用內存數據庫)在另一個xml配置中,您只需在新配置中使用<context:property-override ..."/>,並使用包含格式爲beanName.property=newvalue的鍵值的.properties文件覆蓋主要道具。

應用mainConfig.xml:

<bean id="dataSource" 
    class="org.apache.commons.dbcp.BasicDataSource" 
    p:driverClassName="org.postgresql.Driver" 
    p:url="jdbc:postgresql://localhost:5432/MyAppDB" 
    p:username="myusername" 
    p:password="mypassword" 
    destroy-method="close" /> 

應用testConfig.xml:

<import resource="classpath:path/to/file/application-mainConfig.xml"/> 

<!-- override bean props --> 
<context:property-override location="classpath:path/to/file/beanOverride.properties"/> 

beanOverride.properties:

dataSource.driverClassName=org.h2.Driver 
dataSource.url=jdbc:h2:mem:MyTestDB