2

當(dāng)構(gòu)造函數(shù)有2個相同類型的參數(shù),指定次序可以解決此種情況。注意index是從0開始

    <bean id="exampleBean" class="examples.ExampleBean">
        <constructor-arg name="years" value="7500000"/>
        <constructor-arg name="ultimateAnswer" value="42"/>
    </bean>

記住砰嘁,若要使Spring能從構(gòu)造函數(shù)查找參數(shù)名字,代碼在編譯時必須開啟調(diào)試模式秉撇。若你沒有開啟調(diào)試模式(或者不想),可以使用@ConstructorProperties JDK 注解明確指定構(gòu)造參數(shù)的name。樣例程序:

package examples;

public class ExampleBean {

    // Fields omitted

    @ConstructorProperties({"years", "ultimateAnswer"})
    public ExampleBean(int years, String ultimateAnswer) {
        this.years = years;
        this.ultimateAnswer = ultimateAnswer;
    }

}

<h5 id='beans-setter-injection'>setter注入</h5>
Setter注入是容器調(diào)用bean上的setter方法,bean是使用無參構(gòu)造函數(shù)返回的實例新荤,或者無參靜態(tài)工廠方法返回的實例。
下面樣例中展示了只能使用Setter注入的類台汇。這個類是傳統(tǒng)java類苛骨,就是個POJO,不依賴容器指定的接口苟呐、基類痒芝、注解。

public class SimpleMovieLister {

    // the SimpleMovieLister has a dependency on the MovieFinder
    private MovieFinder movieFinder;

    // a setter method so that the Spring container can inject a MovieFinder
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    // business logic that actually uses the injected MovieFinder is omitted...
}

ApplicationContext對它所管理的bean支持構(gòu)造注入和setter注入牵素。也支持先構(gòu)造注入再setter注入严衬。定義依賴,會轉(zhuǎn)換成某種形式的<code class="scode">BeanDefinition</code>類笆呆,<code class="scode">BeanDefinition</code>類與<code class="scode">PropertyEditor</code>實例配合请琳,即可將屬性從一種格式轉(zhuǎn)換成其他格式。然而赠幕,大多數(shù)程序員不會直接使用這些類(也就是編程式)俄精,更多的是使用XML、注解(也就是<code class="scode">@Component</code><code class="scode">@Controller</code>等等),或者<code class="scode">@Configuration</code>注解的類中的方法上使用 <code class="scode">@Bean</code>榕堰。這些配置數(shù)據(jù)嘀倒,都會在容器內(nèi)部轉(zhuǎn)換成BeanDefinition,用于加載整個Spring Ioc 容器。

構(gòu)造注入對比setter注入

何時使用構(gòu)造注入测蘑,何時使用setter注入,經(jīng)驗法則是:強制依賴用構(gòu)造康二,可選依賴用Setter碳胳。注意,在settter方法上使用<code class="scode">@Required</code>注解即可另屬性強制依賴沫勿。

Spring 團隊建議,構(gòu)造注入的實例是不可變的挨约,不為null的。此外产雹,構(gòu)造注入組件要將完全初始化后的實例返回給客戶端代碼诫惭。還有,大量參數(shù)的構(gòu)造函數(shù)是非常爛的蔓挖,它意味著該類有大量的職責(zé)夕土,得重構(gòu)。

setter注入主要用于可選依賴,類內(nèi)部可以指定默認依賴瘟判。否則類內(nèi)所有使用依賴的地方怨绣,都得進行非空校驗。setter注入的有個好處就是拷获,類可以重配置或者再注入篮撑。因此,使用JMX MBeans進行管理的場景中匆瓜,就非常適合setter注入赢笨。

使用何種依賴注入方式,對于某些類驮吱,非常有意義茧妒。有時協(xié)同第三方類處理,沒有源碼糠馆,由你來決定使用何種方式嘶伟。比如,第三方類未暴露任何setter方法又碌,那么構(gòu)造注入也許就是唯一的可行的注入方式了九昧。

<h5 id="beans-dependency-resolution">依賴處理過程</h5>
容器解析bean依賴如下:

  • ApplicationContext創(chuàng)建后用配置元數(shù)據(jù)中描述的所有bean進行初始化。配置元數(shù)據(jù)格式可以是XML毕匀、Java Code铸鹰,或者注解。
  • 每個bean的依賴皂岔,都會以下列形式表達:屬性蹋笼、構(gòu)造參數(shù),靜態(tài)工廠方法的參數(shù)。當(dāng)bean真正的創(chuàng)建時剖毯,這些依賴會被提供給bean圾笨。
  • 每個屬性或者構(gòu)造函數(shù)或者以value值形式在bean處直接設(shè)置,或者引用容器中其他bean逊谋。
  • 每一個屬性或者構(gòu)造參數(shù)都是一個值擂达,該值將會從指定的格式轉(zhuǎn)換為屬性、構(gòu)造參數(shù)的真正類型胶滋。Spring默認會將一個String類value轉(zhuǎn)換成內(nèi)建類型板鬓,比如int,long,String,boolean等等

Spring容器在創(chuàng)建bean之前會驗證bean的配置。在bean創(chuàng)建之前究恤,bean的屬性不會賦值俭令。當(dāng)容器創(chuàng)建之后,會創(chuàng)建被設(shè)置為預(yù)先初始化的sington-scope單例作用域bean部宿,非單例作用域bean抄腔,只有在請求時才會創(chuàng)建。作用域窟赏,在5.5章有定義妓柜,"Bean 作用域"。一個bean的創(chuàng)建涯穷,可能會引起許多bean的創(chuàng)建棍掐。因為bean的依賴以及依賴的依賴得先創(chuàng)建好用于引用。不涉及首先創(chuàng)建的bean及其依賴類bean拷况,會稍后創(chuàng)建作煌。

循環(huán)依賴
如果你主要使用構(gòu)造注入,可能會創(chuàng)建一個循環(huán)依賴,該依賴不能解析赚瘦。

舉個栗子:類A需要類B的實例粟誓,使用了構(gòu)造注入,類B需要一個類A的實例,也用了構(gòu)造注入起意。若在配置文件中配置類A的bean和類B的bean互相注入鹰服,Spring IoC容器在運行時發(fā)現(xiàn)循環(huán)引用,拋出異常BeanCurrentlyInCreationException揽咕。

一般使用Setter注入替代構(gòu)造注入悲酷,這需要修改源碼改配置,來解決循環(huán)依賴亲善。避免使用構(gòu)造注入或者只使用setter设易,都能避免循環(huán)依賴。 換句話說蛹头,雖然不推薦循環(huán)依賴顿肺,但是你可以使用setter注入來完成循環(huán)依賴戏溺。

和大多數(shù)場景(無循環(huán)引用)不一樣的是,循環(huán)引用中的類A和類B中屠尊,得強制其中一個自己能完全初始化旷祸,然后注入給另一個(經(jīng)典的先有雞現(xiàn)有蛋的問題)。
循環(huán)依賴end

對于Spring讼昆,你經(jīng)管放心肋僧,它非常智能。他能在容器加載期發(fā)現(xiàn)配置中的問題控淡,比如:引用了一個不存在的bean、循環(huán)依賴止潘。Spring在bean創(chuàng)建后掺炭,會盡可能遲的設(shè)置bean屬性并處理依賴。這意味著凭戴,spring容器正確加載之后涧狮,當(dāng)你請求一個對象而該對象的創(chuàng)建有問題或者是該對象的依賴有問題時,也能產(chǎn)生一個異常。舉例來說么夫,因為屬性找不到者冤,或者屬性無效, 導(dǎo)致bean拋出異常档痪。這可能會延遲發(fā)現(xiàn)配置問題涉枫,這就是為什么ApplicationContext默認會預(yù)先實例化單例bean。在這些bean被實際請求之前就創(chuàng)建腐螟,會消耗一些時間和內(nèi)存愿汰,但是在ApplicationContext創(chuàng)建后你就能發(fā)現(xiàn)配置問題,而不是更遲乐纸。如果你愿意 ,也可以重寫該行為衬廷,讓單例bean延遲初始化。

如果沒有循環(huán)依賴汽绢,當(dāng)一個或者多個合作bean被注入到他們的依賴類時吗跋,每一個合作bean將會比依賴類更早的實例化。也就是說宁昭,如果bean A依賴bean B跌宛,Spring Ioc容器在調(diào)用A的setter方法之前,會先實例化B久窟。換句話說秩冈,bean先實例化(非單例),然后設(shè)置依賴斥扛,然后調(diào)用相關(guān)聲明周期方法(比如配置的init方法入问,或者是初始化回調(diào)函數(shù))丹锹。

<h5 id='beans-some-examples'>注入依賴樣例</h5>
The following example uses XML-based configuration metadata for setter-based DI. A small part of a Spring XML configuration file specifies some bean definitions:
下面例子中使用了XML配置元數(shù)據(jù),setter注入方式芬失。XML 配置文件中的片段定義了bean:

<bean id="exampleBean" class="examples.ExampleBean">
    <!-- 使用內(nèi)嵌的ref元素完成setter注入 -->
    <property name="beanOne">
        <ref bean="anotherExampleBean"/>
    </property>

    <!-- 使用ref屬性完成setter注入 -->
    <property name="beanTwo" ref="yetAnotherBean"/>
    <property name="integerProperty" value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

看java代碼

public class ExampleBean {

    private AnotherBean beanOne;
    private YetAnotherBean beanTwo;
    private int i;

    public void setBeanOne(AnotherBean beanOne) {
        this.beanOne = beanOne;
    }

    public void setBeanTwo(YetAnotherBean beanTwo) {
        this.beanTwo = beanTwo;
    }

    public void setIntegerProperty(int i) {
        this.i = i;
    }
}

In the preceding example, setters are declared to match against the properties specified in the XML file. The following example uses constructor-based DI:
上例中楣黍,setter方法名要和XML文件中的property元素的name屬性相匹配。下面演示使用構(gòu)造注入 :

<bean id="exampleBean" class="examples.ExampleBean">
    <!-- constructor injection using the nested ref element -->
    <constructor-arg>
        <ref bean="anotherExampleBean"/>
    </constructor-arg>

    <!-- constructor injection using the neater ref attribute -->
    <constructor-arg ref="yetAnotherBean"/>

    <constructor-arg type="int" value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

看java代碼

public class ExampleBean {

    private AnotherBean beanOne;
    private YetAnotherBean beanTwo;
    private int i;

    public ExampleBean(
        AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {
        this.beanOne = anotherBean;
        this.beanTwo = yetAnotherBean;
        this.i = i;
    }
}

在bean定義中指定的構(gòu)造函數(shù)參數(shù)棱烂,將會賦值給ExampleBean類的參數(shù)租漂。

現(xiàn)在考慮下這個樣例的變種,將使用構(gòu)造器改為靜態(tài)工廠方法返回對象實例:

<bean id="exampleBean" class="examples.ExampleBean" factory-method="createInstance">
    <constructor-arg ref="anotherExampleBean"/>
    <constructor-arg ref="yetAnotherBean"/>
    <constructor-arg value="1"/>
</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

看java代碼

public class ExampleBean {

    //私有構(gòu)造函數(shù)
    private ExampleBean(...) {
        ...
    }

    // 靜態(tài)工廠方法; the arguments to this method can be
    // considered the dependencies of the bean that is returned,
    // regardless of how those arguments are actually used.
    public static ExampleBean createInstance (
        AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {

        ExampleBean eb = new ExampleBean (...);
        // some other operations...
        return eb;
    }

}

靜態(tài)工廠方法的參數(shù)颊糜,應(yīng)該通過constructor-arg元素產(chǎn)生哩治,就像是bean的構(gòu)造函數(shù)一樣.工廠方法返回的類的類型無需和工廠類類型相同,雖然本例中他們是相同的衬鱼。實例工廠方法(非靜態(tài))和靜態(tài)工廠方法本質(zhì)相同(除了使用facory-bean屬性替代class屬性业筏,其他都相同),因此細節(jié)就不討論了鸟赫。

<h4 id='beans-factory-properties-detailed'>依賴和配置詳解</h4>
前面章節(jié)提到的蒜胖,你可以定義的bean的屬性和構(gòu)造參數(shù)引用其他的Spring bean(合作者),或者是使用value屬性設(shè)置其值抛蚤。Spring XML格式配置元數(shù)據(jù)至此<property/><constructor-arg/>子元素台谢,用以實現(xiàn)構(gòu)造注入和屬性注入。

<h5 id="beans-value-element">直接賦值(原始類型岁经、String等等)</h5>
<property />元素的value屬性為對象域?qū)傩曰蛘邩?gòu)造參數(shù)設(shè)置了一個可讀的字串朋沮。Spring的會將其轉(zhuǎn)換為實際的與屬性或者參數(shù)的數(shù)據(jù)類型。

<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <!-- results in a setDriverClassName(String) call -->
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc:mysql://localhost:3306/mydb"/>
    <property name="username" value="root"/>
    <property name="password" value="masterkaoli"/>
</bean>

下面的樣例蒿偎,是使用了XML配置中的p命名空間朽们,他讓XML更加簡潔

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource"
        destroy-method="close"
        p:driverClassName="com.mysql.jdbc.Driver"
        p:url="jdbc:mysql://localhost:3306/mydb"
        p:username="root"
        p:password="masterkaoli"/>

</beans>

上面的XML更簡潔;然而诉位,錯別字骑脱,要在運行期才能發(fā)現(xiàn)而不能再開發(fā)期發(fā)現(xiàn),除非你使用IDE支持自動補全苍糠。這樣的的IDE的助手真心推薦叁丧。

也可以這樣配java.unit.Properties實例:

<bean id="mappings" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <!-- typed as a java.util.Properties -->
    <property name="properties">
        <value>
            jdbc.driver.className=com.mysql.jdbc.Driver
            jdbc.url=jdbc:mysql://localhost:3306/mydb
        </value>
    </property>
</bean>

Spring 容器通過JavaBean的PropertyEditor機制將<value/>元素內(nèi)的值轉(zhuǎn)換到java.util.Properties實例。這是非常棒的岳瞭,Spring團隊最喜歡的幾處好用之處之一:用內(nèi)嵌<value/>元素替代 值屬性風(fēng)格拥娄。

<h5 id='beans-idref-element'>元素<span class="scode">idref</span></h5>
idref元素用來將容器內(nèi)其它bean的id傳給<constructor-arg/><property/>元素,同時提供錯誤驗證功能瞳筏。

<bean id="theTargetBean" class="..."/>

<bean id="theClientBean" class="...">
    <property name="targetName">
        <idref bean="theTargetBean" />
    </property>
</bean>

上面的bean定義在運行時等同于下面這一段定義:

<bean id="theTargetBean" class="..." />

<bean id="client" class="...">
    <property name="targetName" value="theTargetBean" />
</bean>

第一種格式比第二種要跟可取 稚瘾,因為使用idref標簽,在開發(fā)期將允許容器校驗引用bean真是存在姚炕。在第二個中摊欠,對于client bean是屬性 targetName的值則沒有校驗執(zhí)行 .client bean真正的實例化時丢烘,錯別字才會被發(fā)現(xiàn)(可能會導(dǎo)致致命錯)。如果client bean是一個原型bean些椒,這個錯字導(dǎo)致的異常也許會等到部署后才能被發(fā)現(xiàn)播瞳。

注意

在4.0 beans xsd ,idref上的local屬性不在支持免糕。因此它能提供正規(guī)bean引用 赢乓。當(dāng)你升級到4.0的語法時,記得清除已經(jīng)存在于idref元素上的local屬性石窑。

一個老生常談的問題(至少是2.0以前了)牌芋,<idref/>帶來的好處,在使用ProxyFactorybeanbean定義AOP攔截器時松逊,當(dāng)指定攔截器名字是使用<idref/>元素將姜贡,容器會校驗攔截目標是否存在。

<h5 id='beans-ref-element'>引用其他bean(協(xié)作類)</h5>
ref元素是<constructor-arg/>元素和<property/>元素內(nèi)決定性元素棺棵。用它設(shè)置bean的屬性以引用另一個容器管理的bean。引用的bean就是要設(shè)置屬性的bean的依賴熄捍,在設(shè)置屬性值之前它就要被初始化烛恤。(如果協(xié)作類是單例bean,它會在容器初始化時首先完成初始化)余耽。差不多所有的bean都會引用其他對象缚柏。指定id/name的對象的作用域和依賴校驗通過bean,local ,parent屬性來配置。
指定引用bean通常使用<ref/>標簽碟贾,它允許引用本容器或者父容器中任意的bean币喧,無需配置在同一個xml文件中 。<ref/>標簽中bean的屬性值袱耽,使用的被引用bean的id或者name杀餐。

<ref bean="someBean"/>

通過指定目標bean的parent屬性來引用當(dāng)前容器的父容器中的bean。parent屬性的值可以和引用bean的id或者name(引用bean的name之一)相同朱巨,引用的bean必須存在于當(dāng)前容器的父容器中史翘。若容器存在繼承的情況,并且需要封裝現(xiàn)有父容器中的某個bean到一個代理中冀续,就可以用此種引用機制琼讽,一個與parent bean重名的bean。

<!-- 父容器中 -->
<bean id="accountService" class="com.foo.SimpleAccountService">
    <!-- 依賴 -->
</bean>

子容器中

<bean id="accountService" <!-- 和parent bean重名 -->
    class="org.springframework.aop.framework.ProxyFactoryBean">
    <property name="target">
        <ref parent="accountService"/> <!--注意如何引用 parent bean -->
    </property>
    <!-- 其他配置和依賴 -->
</bean>
注意

在4.0 beans xsd 洪唐,ref上的local屬性不在支持钻蹬。因次它不再支持正規(guī)bean的引用 。當(dāng)你升級到到4.0時凭需,記得清除已經(jīng)存在于ref元素上的local屬性问欠。

<h5 id='beans-inner-beans'>內(nèi)部bean</h5>
<property/>元素或者constructor-arg/>元素內(nèi)定義<bean/>元素肝匆,就是所謂的內(nèi)部類。

<bean id="outer" class="...">
    <!-- 不是引用而是定義一個bean -->
    <property name="target">
        <bean class="com.example.Person"> <!-- 這就是內(nèi)部類 -->
            <property name="name" value="Fiona Apple"/>
            <property name="age" value="25"/>
        </bean>
    </property>
</bean>

內(nèi)部bean的定義無需idname溅潜;容器會忽略這些屬性术唬。也會忽略scope標記。內(nèi)部通常是匿名的,伴隨著外部類(的創(chuàng)建)而創(chuàng)建 滚澜。不能引用內(nèi)部bean(ref屬性不能指向內(nèi)部bean)粗仓,除非使用閉合bean標簽。

譯者注设捐,內(nèi)部bean更直觀
fuck goods借浊,上干活

public class Customer {
    private Person person;
 
    public Customer(Person person) {
        this.person = person;
    }
 
    public void setPerson(Person person) {
        this.person = person;
    }
 
    @Override
    public String toString() {
        return "Customer [person=" + person + "]";
    }
}

再來一段

public class Person {
    private String name;
    private String address;
    private int age;
 
    //getter and setter methods
 
    @Override
    public String toString() {
        return "Person [address=" + address + ", 
                               age=" + age + ", name=" + name + "]";
    }   
}

通常情況下,使用在CustomerBeanbean內(nèi)設(shè)置ref屬性值為Personbean的標示符萝招,即完成注入蚂斤。

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
 
    <bean id="CustomerBean" class="com.example.common.Customer">
        <property name="person" ref="PersonBean" />
    </bean>
 
    <bean id="PersonBean" class="com.example.common.Person">
        <property name="name" value="MrChen" />
        <property name="address" value="address1" />
        <property name="age" value="28" />
    </bean>
 
</beans>

In general, it’s fine to reference like this, but since the ‘MrChen’ person bean is only used for Customer bean only, it’s better to declare this ‘MrChen’ person as an inner bean as following :
一般情況下,這樣的引用很好用槐沼。但是如果'MrChen'這個person bean只用于Customer曙蒸。最好是使用內(nèi)部bean來聲明Person,看起來更加直觀岗钩,更具有可讀性.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
 
    <bean id="CustomerBean" class="com.mkyong.common.Customer">
        <property name="person">
            <bean class="com.mkyong.common.Person">
                <property name="name" value="mkyong" />
                <property name="address" value="address1" />
                <property name="age" value="28" />
            </bean>
        </property>
    </bean>
</beans>

This inner bean also supported in constructor injection as following :
內(nèi)部bean也支持構(gòu)造注入

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="CustomerBean" class="com.mkyong.common.Customer">
        <constructor-arg>
            <bean class="com.mkyong.common.Person">
                <property name="name" value="mkyong" />
                <property name="address" value="address1" />
                <property name="age" value="28" />
            </bean>
        </constructor-arg>
    </bean>
</beans>

<h5 id='beans-collection-elements'>集合</h5>
<list/>,<set/>,<map/>,<props/>元素纽窟,用來設(shè)置Java Collection屬性和參數(shù),分別對應(yīng)List,Set,Map,Properties

<bean id="moreComplexObject" class="example.ComplexObject">
    <!--調(diào)用setAdminEmails(java.util.Properties) -->
    <property name="adminEmails">
        <props>
            <prop key="administrator">administrator@example.org</prop>
            <prop key="support">support@example.org</prop>
            <prop key="development">development@example.org</prop>
        </props>
    </property>
    <!-- 調(diào)用setSomeList(java.util.List) -->
    <property name="someList">
        <list>
            <value>a list element followed by a reference</value>
            <ref bean="myDataSource" />
        </list>
    </property>
    <!-- 代用setSomeMap(java.util.Map) -->
    <property name="someMap">
        <map>
            <entry key="an entry" value="just some string"/>
            <entry key ="a ref" value-ref="myDataSource"/>
        </map>
    </property>
    <!-- 調(diào)用 setSomeSet(java.util.Set) -->
    <property name="someSet">
        <set>
            <value>just some string</value>
            <ref bean="myDataSource" />
        </set>
    </property>
</bean>

map.key兼吓,map.value臂港,或者set.value,以可以是以下元素

bean | ref | idref | list | set | map | props | value | null

<h5 id="beans-collection-elements-merging">集合合并</h5>
集合合并
Spring容器也支持集合合并视搏。應(yīng)用開發(fā)者可以定義父集合<list/>,<map/>,<set/>或者<propx/>元素审孽,該元素可以有子集合<list/>,<map/>,<set/>或者<props/>元素集成或者重寫父集合中的值。也就是,子集合中的值是合并父子集合后的值浑娜,其中子集合中的值會覆蓋父集合中的值佑力。
這一章節(jié)討論父-子bean機制。不熟悉父子bean定義機制的筋遭,最好是先去補充下然后回來繼續(xù)
下例中展示了集合合并

<beans>
    <bean id="parent" abstract="true" class="example.ComplexObject">
        <property name="adminEmails">
            <props>
                <prop key="administrator">administrator@example.com</prop>
                <prop key="support">support@example.com</prop>
            </props>
        </property>
    </bean>
    <bean id="child" parent="parent">
        <property name="adminEmails">
            <!-- the merge is specified on the child collection definition -->
            <props merge="true">
                <prop key="sales">sales@example.com</prop>
                <prop key="support">support@example.co.uk</prop>
            </props>
        </property>
    </bean>
<beans>

注意搓萧,在bean child定義中,指定property adminEmails<props/>元素中merge=true屬性宛畦。當(dāng)childbean被容器解析并且實例化時瘸洛,實例有一個adminEmailsProperties集合,該集合包含了父子容器中adminEmails集合合并后的值次和。

administrator=administrator@example.com
sales=sales@example.com
support=support@example.co.uk

Properties集合的將繼承所有父集合中<props/>定義的值反肋,并且重名屬性值會覆蓋父集合中的值.

這個合并行為,同樣可以用在<list/>,<map/>,<set/>類型上踏施。對于<list/>元素石蔗,spring合并行為與List類型的合并一樣罕邀,也就是,spring合并行為維持集合有序养距;父集合中的元素索引位置比子集合元素索引位置靠前诉探。對于Map,Set,Properties集合類型,不存在次序。因此棍厌,沒有次序影響Map,Set,Properties肾胯,這涉及到容器內(nèi)部使用的這些類型的所有實現(xiàn)類。
譯注:這里沒有提到List會不會發(fā)生覆蓋 ,既然沒提到耘纱,那就是List沒有覆蓋行為敬肚。當(dāng)然了,實踐才是王道束析,動手實驗才能驗證推測艳馒,研讀源碼才能知道原理,下面上干貨

Java代碼

public class CollectionMerge {
    private List<String> list;

    public List<String> getList() {
        return list;
    }

    public void setList(List<String> list) {
        this.list = list;
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末员寇,一起剝皮案震驚了整個濱河市弄慰,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蝶锋,老刑警劉巖曹动,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異牲览,居然都是意外死亡,警方通過查閱死者的電腦和手機恶守,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門第献,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人兔港,你說我怎么就攤上這事庸毫。” “怎么了衫樊?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵飒赃,是天一觀的道長。 經(jīng)常有香客問我科侈,道長载佳,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任臀栈,我火速辦了婚禮蔫慧,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘权薯。我一直安慰自己姑躲,他們只是感情好睡扬,可當(dāng)我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著黍析,像睡著了一般卖怜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上阐枣,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天马靠,我揣著相機與錄音,去河邊找鬼侮繁。 笑死虑粥,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的宪哩。 我是一名探鬼主播娩贷,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼锁孟!你這毒婦竟也來了彬祖?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤品抽,失蹤者是張志新(化名)和其女友劉穎储笑,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體圆恤,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡突倍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了盆昙。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片羽历。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖淡喜,靈堂內(nèi)的尸體忽然破棺而出秕磷,到底是詐尸還是另有隱情,我是刑警寧澤炼团,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布澎嚣,位于F島的核電站,受9級特大地震影響瘟芝,放射性物質(zhì)發(fā)生泄漏易桃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一锌俱、第九天 我趴在偏房一處隱蔽的房頂上張望颈抚。 院中可真熱鬧,春花似錦、人聲如沸贩汉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽匹舞。三九已至褐鸥,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間赐稽,已是汗流浹背叫榕。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留姊舵,地道東北人晰绎。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像括丁,于是被迫代替她去往敵國和親荞下。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容