日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

【第三章】 DI 之 3.1 DI的配置使用 ——跟我學(xué)

系統(tǒng) 2323 0

3.1.1? 依賴和依賴注入

?????? 傳統(tǒng)應(yīng)用程序設(shè)計(jì)中所說(shuō)的依賴一般指“類之間的關(guān)系”,那先讓我們復(fù)習(xí)一下類之間的關(guān)系:

? ? ? 泛化: 表示類與類之間的繼承關(guān)系、接口與接口之間的繼承關(guān)系;

? ? ? 實(shí)現(xiàn): 表示類對(duì)接口的實(shí)現(xiàn);

? ? ? 依賴: 當(dāng)類與類之間有使用關(guān)系時(shí)就屬于依賴關(guān)系,不同于關(guān)聯(lián)關(guān)系,依賴不具有“擁有關(guān)系”,而是一種“相識(shí)關(guān)系”,只在某個(gè)特定地方(比如某個(gè)方法體內(nèi))才有關(guān)系。

? ? ? 關(guān)聯(lián): 表示類與類或類與接口之間的依賴關(guān)系,表現(xiàn)為“擁有關(guān)系”;具體到代碼可以用實(shí)例變量來(lái)表示;

? ? ? 聚合: 屬于是關(guān)聯(lián)的特殊情況,體現(xiàn)部分-整體關(guān)系,是一種弱擁有關(guān)系;整體和部分可以有不一樣的生命周期;是一種弱關(guān)聯(lián);

? ? ? 組合: 屬于是關(guān)聯(lián)的特殊情況,也體現(xiàn)了體現(xiàn)部分-整體關(guān)系,是一種強(qiáng)“擁有關(guān)系”;整體與部分有相同的生命周期,是一種強(qiáng)關(guān)聯(lián);

Spring IoC容器的依賴有兩層含義: Bean依賴容器 容器注入Bean的依賴資源

? ? ? Bean依賴容器: 也就是說(shuō)Bean要依賴于容器,這里的依賴是指容器負(fù)責(zé)創(chuàng)建Bean并管理Bean的生命周期,正是由于由容器來(lái)控制創(chuàng)建Bean并注入依賴,也就是控制權(quán)被反轉(zhuǎn)了,這也正是IoC名字的由來(lái), 此處的有依賴是指Bean和容器之間的依賴關(guān)系

? ? ? 容器注入Bean的依賴資源: 容器負(fù)責(zé)注入Bean的依賴資源,依賴資源可以是Bean、外部文件、常量數(shù)據(jù)等,在Java中都反映為對(duì)象,并且由容器負(fù)責(zé)組裝Bean之間的依賴關(guān)系, 此處的依賴是指Bean之間的依賴關(guān)系 可以認(rèn)為是傳統(tǒng)類與類之間的“關(guān)聯(lián)”、“聚合”、“組合”關(guān)系

?

為什么要應(yīng)用依賴注入,應(yīng)用依賴注入能給我們帶來(lái)哪些好處呢?

? ? ? 動(dòng)態(tài)替換Bean依賴對(duì)象,程序更靈活: 替換Bean依賴對(duì)象,無(wú)需修改源文件:應(yīng)用依賴注入后,由于可以采用配置文件方式實(shí)現(xiàn),從而能隨時(shí)動(dòng)態(tài)的替換Bean的依賴對(duì)象,無(wú)需修改java源文件;

? ? ? 更好實(shí)踐面向接口編程,代碼更清晰: 在Bean中只需指定依賴對(duì)象的接口,接口定義依賴對(duì)象完成的功能,通過(guò)容器注入依賴實(shí)現(xiàn);

? ? ? 更好實(shí)踐優(yōu)先使用對(duì)象組合,而不是類繼承: 因?yàn)镮oC容器采用注入依賴,也就是組合對(duì)象,從而更好的實(shí)踐對(duì)象組合。

  • 采用對(duì)象組合,Bean的功能可能由幾個(gè)依賴Bean的功能組合而成,其Bean本身可能只提供少許功能或根本無(wú)任何功能,全部委托給依賴Bean,對(duì)象組合具有動(dòng)態(tài)性,能更方便的替換掉依賴Bean,從而改變Bean功能;
  • 而如果采用類繼承,Bean沒(méi)有依賴Bean,而是采用繼承方式添加新功能,,而且功能是在編譯時(shí)就確定了,不具有動(dòng)態(tài)性,而且采用類繼承導(dǎo)致Bean與子Bean之間高度耦合,難以復(fù)用。

? ? ? 增加Bean可復(fù)用性: 依賴于對(duì)象組合,Bean更可復(fù)用且復(fù)用更簡(jiǎn)單;

? ? ? 降低Bean之間耦合: 由于我們完全采用面向接口編程,在代碼中沒(méi)有直接引用Bean依賴實(shí)現(xiàn),全部引用接口,而且不會(huì)出現(xiàn)顯示的創(chuàng)建依賴對(duì)象代碼,而且這些依賴是由容器來(lái)注入,很容易替換依賴實(shí)現(xiàn)類,從而降低Bean與依賴之間耦合;

? ? ? 代碼結(jié)構(gòu)更清晰: 要應(yīng)用依賴注入,代碼結(jié)構(gòu)要按照規(guī)約方式進(jìn)行書寫,從而更好的應(yīng)用一些最佳實(shí)踐,因此代碼結(jié)構(gòu)更清晰。

?

從以上我們可以看出,其實(shí)依賴注入只是一種裝配對(duì)象的手段,設(shè)計(jì)的類結(jié)構(gòu)才是基礎(chǔ),如果設(shè)計(jì)的類結(jié)構(gòu)不支持依賴注入,Spring IoC容器也注入不了任何東西,從而從根本上說(shuō) “如何設(shè)計(jì)好類結(jié)構(gòu)才是關(guān)鍵,依賴注入只是一種裝配對(duì)象手段”。

前邊IoC一章我們已經(jīng)了解了Bean依賴容器,那容器如何注入Bean的依賴資源,Spring IoC容器注入依賴資源主要有以下兩種基本實(shí)現(xiàn)方式:

? ? ? 構(gòu)造器注入: 就是容器實(shí)例化Bean時(shí)注入那些依賴,通過(guò)在在Bean定義中指定構(gòu)造器參數(shù)進(jìn)行注入依賴,包括實(shí)例工廠方法參數(shù)注入依賴,但靜態(tài)工廠方法參數(shù)不允許注入依賴;

? ? ? setter注入 :通過(guò)setter方法進(jìn)行注入依賴;

? ? ? 方法注入 :能通過(guò)配置方式替換掉Bean方法,也就是通過(guò)配置改變Bean方法 功能。

?

我們已經(jīng)知道注入實(shí)現(xiàn)方式了,接下來(lái)讓我們來(lái)看看具體配置吧。

?

?

3.1.2? 構(gòu)造器注入

?????? 使用構(gòu)造器注入通過(guò)配置構(gòu)造器參數(shù)實(shí)現(xiàn),構(gòu)造器參數(shù)就是依賴。除了構(gòu)造器方式,還有靜態(tài)工廠、實(shí)例工廠方法可以進(jìn)行構(gòu)造器注入。如圖3-1所示:

?

圖3-1 實(shí)例化

構(gòu)造器注入可以根據(jù)參數(shù)索引注入、參數(shù)類型注入或Spring3支持的參數(shù)名注入,但參數(shù)名注入是有限制的,需要使用在編譯程序時(shí)打開(kāi)調(diào)試模式(即在編譯時(shí)使用“javac –g:vars”在class文件中生成變量調(diào)試信息,默認(rèn)是不包含變量調(diào)試信息的,從而能獲取參數(shù)名字,否則獲取不到參數(shù)名字)或在構(gòu)造器上使用@ConstructorProperties(java.beans.ConstructorProperties)注解來(lái)指定參數(shù)名。

首先讓我們準(zhǔn)備測(cè)試構(gòu)造器類HelloImpl3.java,該類只有一個(gè)包含兩個(gè)參數(shù)的構(gòu)造器:

?

java代碼:
  1. package ?cn.javass.spring.chapter3.helloworld;??
  2. public ? class ?HelloImpl3? implements ?HelloApi?{??
  3. ???? private ?String?message;??
  4. private ? int ?index;??
  5. //@java.beans.ConstructorProperties({"message",?"index"}) ??
  6. ???? public ?HelloImpl3(String?message,? int ?index)?{??
  7. ???????? this .message?=?message;??
  8. ???????? this .index?=?index;??
  9. ????}??
  10. ???? @Override ??
  11. ???? public ? void ?sayHello()?{??
  12. ????????System.out.println(index?+? ":" ?+?message);??
  13. ????}??
  14. }??

?

一、根據(jù)參數(shù)索引注入,使用標(biāo)簽“<constructor-arg index="1" value="1"/>”來(lái)指定注入的依賴,其中“index”表示索引,從0開(kāi)始,即第一個(gè)參數(shù)索引為0,“value”來(lái)指定注入的常量值,配置方式如下:

??????

二、根據(jù)參數(shù)類型進(jìn)行注入,使用標(biāo)簽“<constructor-arg type="java.lang.String" value="Hello World!"/>”來(lái)指定注入的依賴,其中“type”表示需要匹配的參數(shù)類型,可以是基本類型也可以是其他類型,如“int”、“java.lang.String”,“value”來(lái)指定注入的常量值,配置方式如下:

?

三、根據(jù)參數(shù)名進(jìn)行注入,使用標(biāo)簽“<constructor-arg name="message" value="Hello World!"/>”來(lái)指定注入的依賴,其中“name”表示需要匹配的參數(shù)名字,“value”來(lái)指定注入的常量值,配置方式如下:

??

四、讓我們來(lái)用具體的例子來(lái)看一下構(gòu)造器注入怎么使用吧。

(1)首先準(zhǔn)備Bean類,在此我們就使用“HelloImpl3”這個(gè)類。

(2)有了Bean類,接下來(lái)要進(jìn)行Bean定義配置,我們需要配置三個(gè)Bean來(lái)完成上述三種依賴注入測(cè)試,其中Bean ”byIndex”是通過(guò)索引注入依賴;Bean ”byType”是根據(jù)類型進(jìn)行注入依賴;Bean ”byName”是根據(jù)參數(shù)名字進(jìn)行注入依賴,具體配置文件(resources/chapter3/ constructorDependencyInject.xml)如下:

?

java代碼:
  1. <!--?通過(guò)構(gòu)造器參數(shù)索引方式依賴注入?-->??
  2. <bean?id= "byIndex" ? class = "cn.javass.spring.chapter3.HelloImpl3" >??
  3. <constructor-arg?index= "0" ?value= "Hello?World!" />??
  4. ????<constructor-arg?index= "1" ?value= "1" />??
  5. </bean>??
  6. <!--?通過(guò)構(gòu)造器參數(shù)類型方式依賴注入?-->??
  7. <bean?id= "byType" ? class = "cn.javass.spring.chapter3.HelloImpl3" >??
  8. ???<constructor-arg?type= "java.lang.String" ?value= "Hello?World!" />??
  9. ???<constructor-arg?type= "int" ?value= "2" />??
  10. </bean>??
  11. <!--?通過(guò)構(gòu)造器參數(shù)名稱方式依賴注入?-->??
  12. <bean?id= "byName" ? class = "cn.javass.spring.chapter3.HelloImpl3" >??
  13. ???<constructor-arg?name= "message" ?value= "Hello?World!" />??
  14. ???<constructor-arg?name= "index" ?value= "3" />??
  15. </bean>??
  16. ???
  17. ???

?

(3)配置完畢后,在測(cè)試之前,因?yàn)槲覀兪褂昧送ㄟ^(guò)構(gòu)造器參數(shù)名字注入方式,請(qǐng)確保編譯時(shí)class文件包含“變量信息”,具體查看編譯時(shí)是否包含“變量調(diào)試信息”請(qǐng)右擊項(xiàng)目,在彈出的對(duì)話框選擇屬性;然后在彈出的對(duì)話框選擇“Java Compiler”條目,在“Class 文件 生成”框中選擇“添加變量信息到Class文件(調(diào)試器使用)”,具體如圖3-2:

?

圖3-2 編譯時(shí)打開(kāi)“添加變量信息選項(xiàng)”

(4)接下來(lái)讓我們測(cè)試一下配置是否工作,具體測(cè)試代碼(cn.javass.spring.chapter3. DependencyInjectTest)如下:

?

java代碼:
  1. @Test ??
  2. public ? void ?testConstructorDependencyInjectTest()?{????????
  3. BeanFactory?beanFactory?=?? new ?ClassPathXmlApplicationContext( "chapter3/constructorDependencyInject.xml" );??
  4. //獲取根據(jù)參數(shù)索引依賴注入的Bean ??
  5. HelloApi?byIndex?=?beanFactory.getBean( "byIndex" ,?HelloApi. class );??
  6. byIndex.sayHello();??
  7. //獲取根據(jù)參數(shù)類型依賴注入的Bean ??
  8. HelloApi?byType?=?beanFactory.getBean( "byType" ,?HelloApi. class );??
  9. byType.sayHello();??
  10. //獲取根據(jù)參數(shù)名字依賴注入的Bean ??
  11. HelloApi?byName?=?beanFactory.getBean( "byName" ,?HelloApi. class );??
  12. byName.sayHello();??
  13. }??

?

?????? 通過(guò)以上測(cè)試我們已經(jīng)會(huì)基本的構(gòu)造器注入配置了,在測(cè)試通過(guò)參數(shù)名字注入時(shí),除了可以使用以上方式,還可以通過(guò)在構(gòu)造器上添加@java.beans.ConstructorProperties({"message", "index"})注解來(lái)指定參數(shù)名字,在HelloImpl3構(gòu)造器上把注釋掉的“ConstructorProperties”打開(kāi)就可以了,這個(gè)就留給大家做練習(xí),自己配置然后測(cè)試一下。

?

五、大家已經(jīng)會(huì)了構(gòu)造器注入,那讓我們?cè)倏匆幌蚂o態(tài)工廠方法注入和實(shí)例工廠注入吧,其實(shí)它們注入配置是完全一樣,在此我們只示范一下靜態(tài)工廠注入方式和實(shí)例工廠方式配置,測(cè)試就留給大家自己練習(xí):

?????? (1)靜態(tài)工廠類

? ? ??

java代碼:
  1. //靜態(tài)工廠類 ??
  2. package ?cn.javass.spring.chapter3;??
  3. import ?cn.javass.spring.chapter2.helloworld.HelloApi;??
  4. public ? class ?DependencyInjectByStaticFactory?{??
  5. ??????? public ? static ?HelloApi?newInstance(String?message,? int ?index)?{??
  6. ?????????????? return ? new ?HelloImpl3(message,?index);??
  7. ???????}??
  8. }??

?

?????? ?靜態(tài)工廠類Bean定義配置文件(chapter3/staticFactoryDependencyInject.xml)

?

?

java代碼:
  1. <bean?id= "byIndex" ??
  2. class = "cn.javass.spring.chapter3.DependencyInjectByStaticFactory" ?factory-method= "newInstance" >??
  3. <constructor-arg?index= "0" ?value= "Hello?World!" />??
  4. <constructor-arg?index= "1" ?value= "1" />??
  5. </bean>??
  6. <bean?id= "byType" ??
  7. class = "cn.javass.spring.chapter3.DependencyInjectByStaticFactory" ?factory-method= "newInstance" >??
  8. <constructor-arg?type= "java.lang.String" ?value= "Hello?World!" />??
  9. ???????<constructor-arg?type= "int" ?value= "2" />??
  10. </bean>??
  11. <bean?id= "byName" ??
  12. class = "cn.javass.spring.chapter3.DependencyInjectByStaticFactory" ?factory-method= "newInstance" >??
  13. ???????<constructor-arg?name= "message" ?value= "Hello?World!" />??
  14. ???????<constructor-arg?name= "index" ?value= "3" />??
  15. </bean>??

?

?

(2)實(shí)例工廠類

?

java代碼:
  1. //實(shí)例工廠類 ??
  2. package ?cn.javass.spring.chapter3;??
  3. import ?cn.javass.spring.chapter2.helloworld.HelloApi;??
  4. public ? class ?DependencyInjectByInstanceFactory?{??
  5. ???? public ?HelloApi?newInstance(String?message,? int ?index)?{??
  6. ???????? return ? new ?HelloImpl3(message,?index);??
  7. ????}??
  8. }??

?

? ? ? ? 實(shí)例工廠類Bean定義配置文件(chapter3/instanceFactoryDependencyInject.xml)

?

?

java代碼:
  1. <bean?id= "instanceFactory" ??
  2. class = "cn.javass.spring.chapter3.DependencyInjectByInstanceFactory" />??
  3. ???
  4. <bean?id= "byIndex" ??
  5. factory-bean= "instanceFactory" ??factory-method= "newInstance" >??
  6. ????<constructor-arg?index= "0" ?value= "Hello?World!" />??
  7. ???????<constructor-arg?index= "1" ?value= "1" />??
  8. </bean>??
  9. <bean?id= "byType" ??
  10. factory-bean= "instanceFactory" ?factory-method= "newInstance" >??
  11. <constructor-arg?type= "java.lang.String" ?value= "Hello?World!" />??
  12. <constructor-arg?type= "int" ?value= "2" />??
  13. </bean>??
  14. <bean?id= "byName" ??
  15. factory-bean= "instanceFactory" ?factory-method= "newInstance" >??
  16. <constructor-arg?name= "message" ?value= "Hello?World!" />??
  17. <constructor-arg?name= "index" ?value= "3" />??
  18. </bean>??

?

?????? (3)測(cè)試代碼和構(gòu)造器方式完全一樣,只是配置文件不一樣,大家只需把測(cè)試文件改一下就可以了。還有一點(diǎn)需要大家注意就是靜態(tài)工廠方式和實(shí)例工廠方式根據(jù)參數(shù)名字注入的方式只支持通過(guò)在class文件中添加“變量調(diào)試信息”方式才能運(yùn)行,ConstructorProperties注解方式不能工作,它只對(duì)構(gòu)造器方式起作用, 不建議使用根據(jù)參數(shù)名進(jìn)行構(gòu)造器注入

?

?

3.1.3? setter注入

?????? setter注入,是通過(guò)在通過(guò)構(gòu)造器、靜態(tài)工廠或?qū)嵗S實(shí)例好Bean后,通過(guò)調(diào)用Bean類的setter方法進(jìn)行注入依賴,如圖3-3所示:

?

圖3-3 setter注入方式

?????? setter注入方式只有一種根據(jù)setter名字進(jìn)行注入:

?

?????? 知道配置方式了,接下來(lái)先讓我們來(lái)做個(gè)簡(jiǎn)單例子吧。

?

(1)準(zhǔn)備測(cè)試類HelloImpl4,需要兩個(gè)setter方法“setMessage”和“setIndex”:

?

java代碼:
  1. package ?cn.javass.spring.chapter3;??
  2. import ?cn.javass.spring.chapter2.helloworld.HelloApi;??
  3. public ? class ?HelloImpl4? implements ?HelloApi?{??
  4. ???? private ?String?message;??
  5. ???? private ? int ?index;??
  6. //setter方法 ??
  7. ???? public ? void ?setMessage(String?message)?{??
  8. ???????? this .message?=?message;??
  9. ????}??
  10. ???? public ? void ?setIndex( int ?index)?{??
  11. ???????? this .index?=?index;??
  12. ????}??
  13. ???? @Override ??
  14. ???? public ? void ?sayHello()?{??
  15. ????????System.out.println(index?+? ":" ?+?message);??
  16. ????}??
  17. }??

?

?????? (2)配置Bean定義,具體配置文件(resources/chapter3/setterDependencyInject.xml)片段如下:

?

java代碼:
  1. <!--?通過(guò)setter方式進(jìn)行依賴注入?-->??
  2. ????<bean?id= "bean" ? class = "cn.javass.spring.chapter3.HelloImpl4" >??
  3. ????????<property?name= "message" ?value= "Hello?World!" />??
  4. ????????<property?name= "index" >??
  5. ????????????<value> 1 </value>??
  6. ????????</property>??
  7. ????</bean>??

?

? ? ??

(3)該寫測(cè)試進(jìn)行測(cè)試一下是否滿足能工作了,其實(shí)測(cè)試代碼一點(diǎn)沒(méi)變,變的是配置:

?

java代碼:
  1. @Test ??
  2. public ? void ?testSetterDependencyInject()?{??
  3. ????BeanFactory?beanFactory?=??
  4. new ?ClassPathXmlApplicationContext( "chapter3/setterDependencyInject.xml" );??
  5. ???HelloApi?bean?=?beanFactory.getBean( "bean" ,?HelloApi. class );??
  6. ????bean.sayHello();??
  7. }??

??

?????? 知道如何配置了,但Spring如何知道setter方法?如何將值注入進(jìn)去的呢?其實(shí)方法名是要遵守約定的,setter注入的方法名要遵循“JavaBean getter/setter 方法命名約定”:

?

?

?

? ? ? ?JavaBean:是本質(zhì)就是一個(gè)POJO類,但具有一下限制:

? ? ? ? ?該類必須要 有公共的無(wú)參構(gòu)造器 ,如public HelloImpl4() {};

? ? ? ? ? 屬性為private訪問(wèn)級(jí)別 ,不建議public,如private String message;

? ? ? ? ? 屬性必要時(shí)通過(guò)一組setter(修改器)和getter(訪問(wèn)器)方法來(lái)訪問(wèn)

? ? ? ? ? setter方法,以“set”?開(kāi)頭,后跟首字母大寫的屬性名 ,如“setMesssage”,簡(jiǎn)單屬性一般只有一個(gè)方法參數(shù),方法返回值通常為“void”;

? ? ? ? ?g etter方法,一般屬性以“get”開(kāi)頭,對(duì)于boolean類型一般以“is”開(kāi)頭,后跟首字母大寫的屬性名 ,如“getMesssage”,“isOk”;

? ? ? ? ?還有一些其他特殊情況, 比如屬性有連續(xù)兩個(gè)大寫字母開(kāi)頭,如“URL”,則setter/getter方法為:“setURL”和“getURL” ,其他一些特殊情況請(qǐng)參看“Java Bean”命名規(guī)范。

?

?

3.1.4? 注入常量

?????? 注入常量是依賴注入中最簡(jiǎn)單的。配置方式如下所示:

?

java代碼:
  1. <property?name= "message" ?value= "Hello?World!" />??
  2. 或??
  3. <property?name= "index" ><value> 1 </value></property><span? class = "Apple-style-span" ?style= "font-size:?14px;?white-space:?normal;?background-color:?#ffffff;" >?</span>??

?

?????? 以上兩種方式都可以,從配置來(lái)看第一種更簡(jiǎn)潔。注意此處“value”中指定的全是字符串,由Spring容器將此字符串轉(zhuǎn)換成屬性所需要的類型,如果轉(zhuǎn)換出錯(cuò),將拋出相應(yīng)的異常。

Spring容器目前能對(duì)各種基本類型把配置的String參數(shù)轉(zhuǎn)換為需要的類型。

注:Spring類型轉(zhuǎn)換系統(tǒng)對(duì)于boolean類型進(jìn)行了容錯(cuò)處理,除了可以使用“true/false”標(biāo)準(zhǔn)的Java值進(jìn)行注入,還能使用“yes/no”、“on/off”、“1/0”來(lái)代表“真/假”,所以大家在學(xué)習(xí)或工作中遇到這種類似問(wèn)題不要覺(jué)得是人家配置錯(cuò)了,而是Spring容錯(cuò)做的非常好。

?

java代碼:
  1. 測(cè)試類??
  2. public ? class ?BooleanTestBean?{??
  3. ???? private ? boolean ?success;??
  4. ???? public ? void ?setSuccess( boolean ?success)?{??
  5. ???????? this .success?=?success;??
  6. ????}??
  7. ???? public ? boolean ?isSuccess()?{??
  8. ???????? return ?success;??
  9. ????}??
  10. }??
  11. 配置文件(chapter3/booleanInject.xml)片段:??
  12. <!--? boolean 參數(shù)值可以用on/off?-->??
  13. <bean?id= "bean2" ? class = "cn.javass.spring.chapter3.bean.BooleanTestBean" >??
  14. ????<property?name= "success" ?value= "on" />??
  15. </bean>??
  16. <!--? boolean 參數(shù)值可以用yes/no?-->??
  17. <bean?id= "bean3" ? class = "cn.javass.spring.chapter3.bean.BooleanTestBean" >??
  18. ????<property?name= "success" ?value= "yes" />??
  19. </bean>??
  20. <!--? boolean 參數(shù)值可以用 1 / 0 ?-->??
  21. <bean?id= "bean4" ? class = "cn.javass.spring.chapter3.bean.BooleanTestBean" >??
  22. ????<property?name= "success" ?value= "1" />??
  23. </bean>??

3.1.5?? ?注入Bean ID

用于注入Bean的ID,ID是一個(gè)常量不是引用,且類似于注入常量,但提供錯(cuò)誤驗(yàn)證功能,配置方式如下所示:

?

java代碼:
  1. <property?name= "id" ><idref?bean= "bean1" /></property>??

?

?

java代碼:
  1. <property?name= "id" ><idref?local= "bean2" /></property>??

?

兩種方式都可以,上述配置本質(zhì)上在運(yùn)行時(shí)等于如下方式

?

java代碼:
  1. <bean?id= "bean1" ? class = "……" />??
  2. <bean?id= "idrefBean1" ? class = "……" >??
  3. <property?name= "id" ?value?= "bean1" />??
  4. </bean>??

?

第一種方式可以在容器初始化時(shí)校驗(yàn)被引用的Bean是否存在,如果不存在將拋出異常,而第二種方式只有在Bean實(shí)際使用時(shí)才能發(fā)現(xiàn)傳入的Bean的ID是否正確,可能發(fā)生不可預(yù)料的錯(cuò)誤。因此如果想注入Bean的ID,推薦使用第一種方式。

接下來(lái)學(xué)習(xí)一下如何使用吧:

?

首先定義測(cè)試Bean:

?

java代碼:
  1. package ?cn.javass.spring.chapter3.bean??
  2. public ? class ?IdRefTestBean?{??
  3. ???? private ?String?id;??
  4. ???? public ?String?getId()?{??
  5. ???????? return ?id;??
  6. ????}??
  7. ???? public ? void ?setId(String?id)?{??
  8. ???????? this .id?=?id;??
  9. ????}??
  10. }??

?

其次定義配置文件(chapter3/idRefInject.xml):

?

java代碼:
  1. <bean?id= "bean1" ? class = "java.lang.String" >??
  2. <constructor-arg?index= "0" ?value= "test" />??
  3. </bean>??
  4. <bean?id= "bean2" ? class = "java.lang.String" >??
  5. ????<constructor-arg?index= "0" ?value= "test" />??
  6. </bean>??

?

?

java代碼:
  1. <bean?id= "idrefBean1" ? class = "cn.javass.spring.chapter3.bean.IdRefTestBean" >??
  2. ????????<property?name= "id" ><idref?bean= "bean1" /></property>??
  3. </bean>??
  4. <bean?id= "idrefBean2" ? class = "cn.javass.spring.chapter3.bean.IdRefTestBean" >??
  5. ????<property?name= "id" ><idref?local= "bean2" /></property>??
  6. </bean>??

?

?????? 從配置中可以看出,注入的Bean的ID是一個(gè)java.lang.String類型,即字符串類型,因此注入的同樣是常量,只是具有校驗(yàn)功能。

<idref bean="……"/>將在容器初始化時(shí)校驗(yàn)注入的ID對(duì)于的Bean是否存在,如果不存在將拋出異常。

<idref local="……"/>將在XML解析時(shí)校驗(yàn)注入的ID對(duì)于的Bean在當(dāng)前配置文件中是否存在,如果不存在將拋出異常,它不同于<idref bean="……"/>是校驗(yàn)發(fā)生在XML解析式而非容器初始化時(shí),且只檢查當(dāng)前配置文件中是否存在相應(yīng)的Bean。

?

3.1.6? 注入集合、數(shù)組和字典

?????? Spring不僅能注入簡(jiǎn)單類型數(shù)據(jù),還能注入集合(Collection、無(wú)序集合Set、有序集合List)類型、數(shù)組(Array)類型、字典(Map)類型數(shù)據(jù)、Properties類型數(shù)據(jù),接下來(lái)就讓我們一個(gè)個(gè)看看如何注入這些數(shù)據(jù)類型的數(shù)據(jù)。

???????一、注入集合類型: 包括Collection類型、Set類型、List類型數(shù)據(jù):

???????(1)List類型: 需要使用<list>標(biāo)簽來(lái)配置注入,其具體配置如下:

?

?????? 讓我們來(lái)寫個(gè)測(cè)試來(lái)練習(xí)一下吧:

? ? ? ? ? ? ?準(zhǔn)備測(cè)試類:

?

java代碼:
  1. package ?cn.javass.spring.chapter3.bean;??
  2. import ?java.util.List;??
  3. public ? class ?ListTestBean?{??
  4. ???? private ?List<String>?values;??
  5. ???? public ?List<String>?getValues()?{??
  6. ???????? return ?values;??
  7. ????}??
  8. ???? public ? void ?setValues(List<String>?values)?{??
  9. ???????? this .values?=?values;??
  10. ????}??
  11. }??

?

??????????????進(jìn)行Bean定義,在配置文件(resources/chapter3/listInject.xml)中配置list注入:

?

java代碼:
  1. <bean?id= "listBean" ? class = "cn.javass.spring.chapter3.bean.ListTestBean" >??
  2. ????<property?name= "values" >??
  3. ????????<list>??
  4. ????????????<value> 1 </value>??
  5. ????????????<value> 2 </value>??
  6. ????????????<value> 3 </value>??
  7. ????????</list>??
  8. ???</property>??
  9. </bean>??

?

??????????????測(cè)試代碼:

?

java代碼:
  1. @Test ??
  2. public ? void ?testListInject()?{??
  3. ???BeanFactory?beanFactory?=??
  4. new ?ClassPathXmlApplicationContext( "chapter3/listInject.xml" );??
  5. ListTestBean?listBean?=?beanFactory.getBean( "listBean" ,?ListTestBean. class );??
  6. System.out.println(listBean.getValues().size());??
  7. Assert.assertEquals( 3 ,?listBean.getValues().size());??
  8. }??

?

?

(2)Set類型: 需要使用<set>標(biāo)簽來(lái)配置注入,其配置參數(shù)及含義和<lsit>標(biāo)簽完全一樣,在此就不闡述了:

? ? ? ? ? ? ? 準(zhǔn)備測(cè)試類:

?

java代碼:
  1. package ?cn.javass.spring.chapter3.bean;??
  2. import ?java.util.Collection;??
  3. public ? class ?CollectionTestBean?{??
  4. ???? private ?Collection<String>?values;??
  5. ???? public ? void ?setValues(Collection<String>?values)?{??
  6. ???????? this .values?=?values;??
  7. ????}??
  8. ???? public ?Collection<String>?getValues()?{??
  9. ???????? return ?values;??
  10. ????}??
  11. }??

? ? ? ? ? ??

??????????????進(jìn)行Bean定義,在配置文件(resources/chapter3/listInject.xml)中配置list注入:

?

java代碼:
  1. <bean?id= "setBean" ? class = "cn.javass.spring.chapter3.bean.SetTestBean" >??
  2. <property?name= "values" >??
  3. <set>??
  4. <value> 1 </value>??
  5. <value> 2 </value>??
  6. <value> 3 </value>??
  7. </set>??
  8. </property>??
  9. </bean>??

? ? ? ? ? ? ? 具體測(cè)試代碼就不寫了,和listBean測(cè)試代碼完全一樣。

?

??????? (2)Collection類型: 因?yàn)镃ollection類型是Set和List類型的基類型,所以使用<set>或<list>標(biāo)簽都可以進(jìn)行注入,配置方式完全和以上配置方式一樣,只是將測(cè)試類屬性改成“Collection”類型,如果配置有問(wèn)題,可參考cn.javass.spring.chapter3.DependencyInjectTest測(cè)試類中的testCollectionInject測(cè)試方法中的代碼。

二、 注入數(shù)組類型 :需要使用<array>標(biāo)簽來(lái)配置注入,其中標(biāo)簽屬性“value-type”和“merge”和<list>標(biāo)簽含義完全一樣,具體配置如下:

?

?????? 如果練習(xí)時(shí)遇到配置問(wèn)題,可以參考“cn.javass.spring.chapter3.DependencyInjectTest”測(cè)試類中的testArrayInject測(cè)試方法中的代碼。

?

???????三、注入字典(Map)類型: 字典類型是包含鍵值對(duì)數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu),需要使用<map>標(biāo)簽來(lái)配置注入,其屬性“key-type”和“value-type”分別指定“鍵”和“值”的數(shù)據(jù)類型,其含義和<list>標(biāo)簽的“value-type”含義一樣,在此就不羅嗦了,并使用<key>子標(biāo)簽來(lái)指定鍵數(shù)據(jù),<value>子標(biāo)簽來(lái)指定鍵對(duì)應(yīng)的值數(shù)據(jù),具體配置如下:

?

?????? 如果練習(xí)時(shí)遇到配置問(wèn)題,可以參考“cn.javass.spring.chapter3.DependencyInjectTest”測(cè)試類中的testMapInject測(cè)試方法中的代碼。

四、 Properties注入 :Spring能注入java.util.Properties類型數(shù)據(jù),需要使用<props>標(biāo)簽來(lái)配置注入,鍵和值類型必須是String,不能變,子標(biāo)簽<prop key=”鍵”>值</prop>來(lái)指定鍵值對(duì),具體配置如下:

?

?

如果練習(xí)時(shí)遇到配置問(wèn)題,可以參考cn.javass.spring.chapter3.DependencyInjectTest測(cè)試類中的testPropertiesInject測(cè)試方法中的代碼。

?????? 到此我們已經(jīng)把簡(jiǎn)單類型及集合類型介紹完了,大家可能會(huì)問(wèn)怎么沒(méi)見(jiàn)注入“Bean之間關(guān)系”的例子呢?接下來(lái)就讓我們來(lái)講解配置Bean之間依賴關(guān)系,也就是注入依賴Bean。

?

??

?

3.1.7? 引用其它Bean

?????? 上邊章節(jié)已經(jīng)介紹了注入常量、集合等基本數(shù)據(jù)類型和集合數(shù)據(jù)類型,本小節(jié)將介紹注入依賴Bean及注入內(nèi)部Bean。

?????? 引用其他Bean的步驟與注入常量的步驟一樣,可以通過(guò)構(gòu)造器注入及setter注入引用其他Bean,只是引用其他Bean的注入配置稍微變化了一下:可以將“<constructor-arg index="0" value="Hello World!"/>”和“<property name="message" value="Hello World!"/>”中的value屬性替換成bean屬性,其中bean屬性指定配置文件中的其他Bean的id或別名。另一種是把<value>標(biāo)簽替換為<.ref bean=”beanName”>,bean屬性也是指定配置文件中的其他Bean的id或別名。那讓我們看一下具體配置吧:

?

一、構(gòu)造器注入方式:

(1)通過(guò)” <constructor-arg>”標(biāo)簽的ref屬性來(lái)引用其他Bean,這是最簡(jiǎn)化的配置:

?

(2)通過(guò)” <constructor-arg>”標(biāo)簽的子<ref>標(biāo)簽來(lái)引用其他Bean,使用bean屬性來(lái)指定引用的Bean:

?

???????二、setter注入方式:

(1)通過(guò)” <property>”標(biāo)簽的ref屬性來(lái)引用其他Bean,這是最簡(jiǎn)化的配置:

?

(2)通過(guò)” <property>”標(biāo)簽的子<ref>標(biāo)簽來(lái)引用其他Bean,使用bean屬性來(lái)指定引用的Bean:

?

?

三、接下來(lái)讓我們用個(gè)具體例子來(lái)講解一下具體使用吧:

(1)首先讓我們定義測(cè)試引用Bean的類,在此我們可以使用原有的HelloApi實(shí)現(xiàn),然后再定義一個(gè)裝飾器來(lái)引用其他Bean,具體裝飾類如下:

?

java代碼:
  1. package ?cn.javass.spring.chapter3.bean;??
  2. import ?cn.javass.spring.chapter2.helloworld.HelloApi;??
  3. public ? class ?HelloApiDecorator? implements ?HelloApi?{??
  4. private ?HelloApi?helloApi;??
  5. //空參構(gòu)造器 ??
  6. ???? public ?HelloApiDecorator()?{??
  7. }??
  8. //有參構(gòu)造器 ??
  9. ???? public ?HelloApiDecorator(HelloApi?helloApi)?{??
  10. ???????? this .helloApi?=?helloApi;??
  11. }????
  12. public ? void ?setHelloApi(HelloApi?helloApi)?{??
  13. ???????? this .helloApi?=?helloApi;??
  14. ????}??
  15. ???? @Override ??
  16. ???? public ? void ?sayHello()?{??
  17. ????????System.out.println( "==========裝飾一下===========" );??
  18. ????????helloApi.sayHello();??
  19. ????????System.out.println( "==========裝飾一下===========" );??
  20. ????}??
  21. }??

?

?????? (2)定義好了測(cè)試引用Bean接下來(lái)該在配置文件(resources/chapter3/beanInject.xml)進(jìn)行配置Bean定義了,在此將演示通過(guò)構(gòu)造器及setter方法方式注入依賴Bean:

??????

java代碼:
  1. <!--?定義依賴Bean?-->??
  2. <bean?id= "helloApi" ? class = "cn.javass.spring.chapter2.helloworld.HelloImpl" />??
  3. <!--?通過(guò)構(gòu)造器注入?-->??
  4. <bean?id= "bean1" ? class = "cn.javass.spring.chapter3.bean.HelloApiDecorator" >??
  5. <constructor-arg?index= "0" ?ref= "helloApi" />??
  6. </bean>??
  7. <!--?通過(guò)構(gòu)造器注入?-->??
  8. <bean?id= "bean2" ? class = "cn.javass.spring.chapter3.bean.HelloApiDecorator" >??
  9. ????<property?name= "helloApi" ><ref?bean= "?helloApi" /></property>??
  10. </bean>??

?

?

(3)測(cè)試一下吧,測(cè)試代碼(cn.javass.spring.chapter3.DependencyInjectTest)片段如下:

?

java代碼:
  1. @Test ??
  2. public ? void ?testBeanInject()?{??
  3. ????BeanFactory?beanFactory?=??
  4. new ?ClassPathXmlApplicationContext( "chapter3/beanInject.xml" );??
  5. ???? //通過(guò)構(gòu)造器方式注入 ??
  6. ????HelloApi?bean1?=?beanFactory.getBean( "bean1" ,?HelloApi. class );??
  7. ????bean1.sayHello();??
  8. ???? //通過(guò)setter方式注入 ??
  9. ????HelloApi?bean2?=?beanFactory.getBean( "bean2" ,?HelloApi. class );??
  10. ????bean2.sayHello();??
  11. }??

?

???????四、其他引用方式: 除了最基本配置方式以外,Spring還提供了另外兩種更高級(jí)的配置方式,<ref local=””/>和<ref parent=””/>

??????? (1)<ref local=””/>配置方式:用于引用通過(guò)<bean id=”beanName”>方式中通過(guò)id屬性指定的Bean,它能利用XML解析器的驗(yàn)證功能在讀取配置文件時(shí)來(lái)驗(yàn)證引用的Bean是否存在。因此如果在當(dāng)前配置文件中有相互引用的Bean可以采用<ref local>方式從而如果配置錯(cuò)誤能在開(kāi)發(fā)調(diào)試時(shí)就發(fā)現(xiàn)錯(cuò)誤。

如果引用一個(gè)在當(dāng)前配置文件中不存在的Bean將拋出如下異常:

org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line21 inXML document from class path resource [chapter3/beanInject2.xml] is invalid; nested exception is org.xml.sax.SAXParseException: cvc-id.1: There is no ID/IDREF binding for IDREF 'helloApi'.

<ref local>具體配置方式如下:

?

?????? (2)<ref parent=””/>配置方式:用于引用父容器中的Bean,不會(huì)引用當(dāng)前容器中的Bean,當(dāng)然父容器中的Bean和當(dāng)前容器的Bean是可以重名的,獲取順序是先查找當(dāng)前容器中的Bean,如果找不到再?gòu)母溉萜髡摇>唧w配置方式如下:

接下來(lái)讓我們用個(gè)例子演示一下<ref local>和<ref parent>的配置過(guò)程:

首先還是準(zhǔn)備測(cè)試類,在此我們就使用以前寫好的HelloApiDecorator和HelloImpl4類;其次進(jìn)行Bean定義,其中當(dāng)前容器bean1引用本地的”helloApi”,而”bean2”將引用父容器的”helloApi”,配置如下:

?

java代碼:
  1. <!--?sources/chapter3/parentBeanInject.xml表示父容器配置-->??
  2. <!--注意此處可能子容器也定義一個(gè)該Bean-->??
  3. <bean?id= "helloApi" ? class = "cn.javass.spring.chapter3.HelloImpl4" >??
  4. <property?name= "index" ?value= "1" />??
  5. <property?name= "message" ?value= "Hello?Parent!" />??
  6. </bean>??

?

?

java代碼:
  1. <!--?sources/chapter3/localBeanInject.xml表示當(dāng)前容器配置-->??
  2. <!--?注意父容器中也定義了id?為?helloApi的Bean?-->??
  3. <bean?id= "helloApi" ? class = "cn.javass.spring.chapter3.HelloImpl4" >??
  4. <property?name= "index" ?value= "1" />??
  5. ????<property?name= "message" ?value= "Hello?Local!" />??
  6. </bean>??
  7. <!--?通過(guò)local注入?-->??
  8. <bean?id= "bean1" ? class = "cn.javass.spring.chapter3.bean.HelloApiDecorator" >??
  9. <constructor-arg?index= "0" ><ref?local= "helloApi" /></constructor-arg>??
  10. </bean>??
  11. <!--?通過(guò)parent注入?-->??
  12. <bean?id= "bean2" ? class = "cn.javass.spring.chapter3.bean.HelloApiDecorator" >??
  13. <property?name= "helloApi" ><ref?parent= "helloApi" /></property>??
  14. </bean>??

?

(3)寫測(cè)試類測(cè)試一下吧,具體代碼片段如下:?

?

java代碼:
  1. @Test ??
  2. public ? void ?testLocalAndparentBeanInject()?{??
  3. //初始化父容器 ??
  4. ApplicationContext?parentBeanContext?=??
  5. new ?ClassPathXmlApplicationContext( "chapter3/parentBeanInject.xml" );??
  6. //初始化當(dāng)前容器 ??
  7. ApplicationContext?beanContext?=? new ?ClassPathXmlApplicationContext(??
  8. new ?String[]?{ "chapter3/localBeanInject.xml" },?parentBeanContext);??
  9. ????HelloApi?bean1?=?beanContext.getBean( "bean1" ,?HelloApi. class );??
  10. ????bean1.sayHello(); //該Bean引用local?bean ??
  11. HelloApi?bean2?=?beanContext.getBean( "bean2" ,?HelloApi. class );??
  12. bean2.sayHello(); //該Bean引用parent?bean ??
  13. }??

?

?“bean1”將輸出“Hello Local!”表示引用當(dāng)前容器的Bean,”bean2”將輸出“Hello Paren!”,表示引用父容器的Bean,如配置有問(wèn)題請(qǐng)參考cn.javass.spring.chapter3.DependencyInjectTest中的testLocalAndparentBeanInject測(cè)試方法。

?

3.1.8? 內(nèi)部Bean定義

內(nèi)部Bean就是在<property>或<constructor-arg>內(nèi)通過(guò)<bean>標(biāo)簽定義的Bean,該Bean不管是否指定id或name,該Bean都會(huì)有唯一的匿名標(biāo)識(shí)符,而且不能指定別名,該內(nèi)部Bean對(duì)其他外部Bean不可見(jiàn),具體配置如下:

?

(1)讓我們寫個(gè)例子測(cè)試一下吧,具體配置文件如下:

?

java代碼:
  1. <bean?id= "bean" ? class = "cn.javass.spring.chapter3.bean.HelloApiDecorator" >??
  2. <property?name= "helloApi" >??
  3. <bean?id= "helloApi" ? class = "cn.javass.spring.chapter2.helloworld.HelloImpl" />??
  4. </property>??
  5. </bean>??

?

?

?(2)測(cè)試代碼(cn.javass.spring.chapter3.DependencyInjectTest.testInnerBeanInject):

?

java代碼:
  1. @Test ??
  2. public ? void ?testInnerBeanInject()?{??
  3. ApplicationContext?context?=??
  4. new ?ClassPathXmlApplicationContext( "chapter3/innerBeanInject.xml" );??
  5. HelloApi?bean?=?context.getBean( "bean" ,?HelloApi. class );??
  6. bean.sayHello();??
  7. }??

?

3.1.9? 處理null值

?????? ?Spring通過(guò)<value>標(biāo)簽或value屬性注入常量值,所有注入的數(shù)據(jù)都是字符串,那如何注入null值呢?通過(guò)“null”值嗎?當(dāng)然不是因?yàn)槿绻⑷搿皀ull”則認(rèn)為是字符串。Spring通過(guò)<null/>標(biāo)簽注入null值。即可以采用如下配置方式:

?

3.1.10 對(duì)象圖導(dǎo)航注入支持

?????? 所謂對(duì)象圖導(dǎo)航是指類似a.b.c這種點(diǎn)綴訪問(wèn)形式的訪問(wèn)或修改值。Spring支持對(duì)象圖導(dǎo)航方式依賴注入。對(duì)象圖導(dǎo)航依賴注入有一個(gè)限制就是比如a.b.c對(duì)象導(dǎo)航圖注入中a和b必須為非null值才能注入c,否則將拋出空指針異常。

?????? Spring不僅支持對(duì)象的導(dǎo)航,還支持?jǐn)?shù)組、列表、字典、Properties數(shù)據(jù)類型的導(dǎo)航,對(duì)Set數(shù)據(jù)類型無(wú)法支持,因?yàn)闊o(wú)法導(dǎo)航。

數(shù)組和列表數(shù)據(jù)類型可以用array[0]、list[1]導(dǎo)航,注意”[]”里的必須是數(shù)字,因?yàn)槭前凑账饕M(jìn)行導(dǎo)航,對(duì)于數(shù)組類型注意不要數(shù)組越界錯(cuò)誤。

字典Map數(shù)據(jù)類型可以使用map[1]、map[str]進(jìn)行導(dǎo)航,其中“[]”里的是基本類型,無(wú)法放置引用類型。

?????? 讓我們來(lái)練習(xí)一下吧。首先準(zhǔn)備測(cè)試類,在此我們需要三個(gè)測(cè)試類,以便實(shí)現(xiàn)對(duì)象圖導(dǎo)航功能演示:

?????? ?NavigationC類用于打印測(cè)試代碼,從而觀察配置是否正確;具體類如下所示:

?

java代碼:
  1. package ?cn.javass.spring.chapter3.bean;??
  2. public ? class ?NavigationC?{??
  3. ???? public ? void ?sayNavigation()?{??
  4. ????????System.out.println( "===navigation?c" );??
  5. ????}??
  6. }??

?

?? ?NavigationB類,包含對(duì)象和列表、Properties、數(shù)組字典數(shù)據(jù)類型導(dǎo)航,而且這些復(fù)合數(shù)據(jù)類型保存的條目都是對(duì)象,正好練習(xí)一下如何往復(fù)合數(shù)據(jù)類型中注入對(duì)象依賴。具體類如下所示:

?

?

java代碼:
  1. package ?cn.javass.spring.chapter3.bean;??
  2. import ?java.util.List;??
  3. import ?java.util.Map;??
  4. import ?java.util.Properties;??
  5. public ? class ?NavigationB?{??
  6. ???? private ?NavigationC?navigationC;??
  7. ???? private ?List<NavigationC>?list;??
  8. ???? private ?Properties?properties;??
  9. ???? private ?NavigationC[]?array?=? new ?NavigationC[ 1 ];??
  10. ???? private ?Map<String,?NavigationC>?map;??
  11. ??? //由于setter和getter方法占用太多空間,故省略,大家自己實(shí)現(xiàn)吧 ??
  12. }??

?

?????? ?NavigationA類是我們的前端類,通過(guò)對(duì)它的導(dǎo)航進(jìn)行注入值,具體代碼如下:

?

java代碼:
  1. package ?cn.javass.spring.chapter3.bean;??
  2. public ? class ?NavigationA?{??
  3. ???? private ?NavigationB?navigationB;??
  4. ???? public ? void ?setNavigationB(NavigationB?navigationB)?{??
  5. ???????? this .navigationB?=?navigationB;??
  6. ????}??
  7. ???? public ?NavigationB?getNavigationB()?{??
  8. ???????? return ?navigationB;??
  9. ????}??
  10. }??

?

?????? ?接下來(lái)該進(jìn)行Bean定義配置(resources/chapter3/navigationBeanInject.xml)了,首先讓我們配置一下需要被導(dǎo)航的數(shù)據(jù),NavigationC和NavigationB類,其中配置NavigationB時(shí)注意要確保比如array字段不為空值,這就需要或者在代碼中賦值如“NavigationC[] array = new NavigationC[1];”,或者通過(guò)配置文件注入如“<list></list>”注入一個(gè)不包含條目的列表。具體配置如下:

?

java代碼:
  1. <bean?id= "c" ? class = "cn.javass.spring.chapter3.bean.NavigationC" />??
  2. <bean?id= "b" ? class = "cn.javass.spring.chapter3.bean.NavigationB" >??
  3. <property?name= "list" ><list></list></property>??
  4. ????<property?name= "map" ><map></map></property>??
  5. ????<property?name= "properties" ><props></props></property>??
  6. </bean>??

?

?????? ? 配置完需要被導(dǎo)航的Bean定義了,該來(lái)配置NavigationA導(dǎo)航Bean了,在此需要注意,由于“navigationB”屬性為空值,在此需要首先注入“navigationB”值;還有對(duì)于數(shù)組導(dǎo)航不能越界否則報(bào)錯(cuò);具體配置如下:

?

java代碼:
  1. <bean?id= "a" ? class = "cn.javass.spring.chapter3.bean.NavigationA" >??
  2. <!--?首先注入navigatiionB?確保它非空?-->??
  3. <property?name= "navigationB" ?ref= "b" />??
  4. <!--?對(duì)象圖導(dǎo)航注入?-->??
  5. <property?name= "navigationB.navigationC" ?ref= "c" />??
  6. <!--?注入列表數(shù)據(jù)類型數(shù)據(jù)?-->??
  7. <property?name= "navigationB.list[0]" ?ref= "c" />??
  8. <!--?注入map類型數(shù)據(jù)?-->??
  9. <property?name= "navigationB.map[key]" ?ref= "c" />??
  10. <!--?注入properties類型數(shù)據(jù)?-->??
  11. <property?name= "navigationB.properties[0]" ?ref= "c" />??
  12. <!--?注入properties類型數(shù)據(jù)?-->??
  13. <property?name= "navigationB.properties[1]" ?ref= "c" />??
  14. <!--?注入數(shù)組類型數(shù)據(jù)?,注意不要越界-->??
  15. <property?name= "navigationB.array[0]" ?ref= "c" />??
  16. </bean>??
  17. ???

?????? ?配置完畢,具體測(cè)試代碼在cn.javass.spring.chapter3. DependencyInjectTest,讓我們看下測(cè)試代碼吧:

?

java代碼:
  1. //對(duì)象圖導(dǎo)航 ??
  2. @Test ??
  3. public ? void ?testNavigationBeanInject()?{??
  4. ApplicationContext?context?=??
  5. new ?ClassPathXmlApplicationContext( "chapter3/navigationBeanInject.xml" );?????????
  6. NavigationA?navigationA?=?context.getBean( "a" ,?NavigationA. class );??
  7. navigationA.getNavigationB().getNavigationC().sayNavigation();??
  8. navigationA.getNavigationB().getList().get( 0 ).sayNavigation();??
  9. navigationA.getNavigationB().getMap().get( "key" ).sayNavigation();??
  10. navigationA.getNavigationB().getArray()[ 0 ].sayNavigation();??
  11. ((NavigationC)navigationA.getNavigationB().getProperties().get( "1" ))??
  12. .sayNavigation();?????????
  13. }??
  14. ???

?

?????? 測(cè)試完畢,應(yīng)該輸出5個(gè)“===navigation c”,是不是很簡(jiǎn)單,注意這種方式是不推薦使用的,了解一下就夠了,最好使用3.1.5一節(jié)使用的配置方式。

?????? ??????

3.1.11配置簡(jiǎn)寫

讓我們來(lái)總結(jié)一下依賴注入配置及簡(jiǎn)寫形式,其實(shí)我們已經(jīng)在以上部分穿插著進(jìn)行簡(jiǎn)化配置了:

?

一、構(gòu)造器注入:

1)常量值

簡(jiǎn)寫:<constructor-arg index="0" value="常量"/>

全寫:<constructor-arg index="0"><value>常量</value></constructor-arg>

2)引用

簡(jiǎn)寫:<constructor-arg index="0" ref="引用"/>

全寫:<constructor-arg index="0"><ref bean="引用"/></constructor-arg>

?

二、setter注入: ??????

?????? 1)常量值

?????? ?簡(jiǎn)寫:<property name="message" value="常量"/>

? ? ? ? 全寫:<property name="message"><value>常量</value></ property>

?????? 2)引用

?????? ?簡(jiǎn)寫:<property name="message" ref="引用"/>

? ? ? ? 全寫:<property name="message"><ref bean="引用"/></ property>

?????? 3)數(shù)組:<array>沒(méi)有簡(jiǎn)寫形式

?????? 4)列表:<list>沒(méi)有簡(jiǎn)寫形式

?????? 5)集合:<set>沒(méi)有簡(jiǎn)寫形式

?????? 6)字典

? ? ? ? ? 簡(jiǎn)寫:<map>

???????????? <entry key="鍵常量" value="值常量"/>

???????????? <entry key-ref="鍵引用" value-ref="值引用"/>

??????????? </map>

? ? ? ? ?全寫:<map>

???????????? <entry><key><value>鍵常量</value></key><value>值常量</value></entry>

???????????? <entry><key><ref bean="鍵引用"/></key><ref bean="值引用"/></entry>

?????????? </map>

?????? 7)Properties:沒(méi)有簡(jiǎn)寫形式

?

三、使用p命名空間簡(jiǎn)化setter注入:

?????? 使用p命名空間來(lái)簡(jiǎn)化setter注入,具體使用如下:

?????????????

?

java代碼:
  1. <?xml?version= "1.0" ?encoding= "UTF-8" ?>??
  2. <beans??xmlns= "http://www.springframework.org/schema/beans" ??
  3. ????????xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" ??
  4. ????????xmlns:p= "http://www.springframework.org/schema/p" ??
  5. ????????xsi:schemaLocation="??
  6. ???????????http: //www.springframework.org/schema/beans ??
  7. ???????????http: //www.springframework.org/schema/beans/spring-beans-3.0.xsd"> ??
  8. <bean?id= "bean1" ? class = "java.lang.String" >??
  9. ????????<constructor-arg?index= "0" ?value= "test" />??
  10. ????</bean>??
  11. <bean?id= "idrefBean1" ? class = "cn.javass.spring.chapter3.bean.IdRefTestBean" ??
  12. p:id= "value" />??
  13. <bean?id= "idrefBean2" ? class = "cn.javass.spring.chapter3.bean.IdRefTestBean" ??
  14. p:id-ref= "bean1" />??
  15. </beans>??
  • xmlns:p="http://www.springframework.org/schema/p"?:首先指定p命名空間;
  • <bean id="……" class="……" p:id="value"/>?: 常量setter注入方式,其等價(jià)于<property name="id" value="value"/>;
      • <bean id="……" class="……" p:id-ref="bean1"/>?: 引用setter注入方式,其等價(jià)于<property name="id" ref="bean1"/>。?
?
?
同步發(fā)布到私塾在線【 http://***/forum/blogPost/list/2447.html

【第三章】 DI 之 3.1 DI的配置使用 ——跟我學(xué)spring3


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 册亨县| 霍邱县| 阜阳市| 石楼县| 那曲县| 泸定县| 青岛市| 许昌市| 西林县| 合肥市| 金乡县| 丹寨县| 竹溪县| 扎鲁特旗| 铁力市| 会泽县| 株洲市| 郯城县| 新乐市| 天峨县| 呼和浩特市| 保德县| 内江市| 武安市| 沈丘县| 织金县| 望都县| 洛浦县| 武义县| 柘荣县| 江北区| 甘洛县| 南雄市| 老河口市| 株洲市| 军事| 镶黄旗| 玛曲县| 乐山市| 长海县| 七台河市|