前言
眾所周知在Spring剛出現(xiàn)的時候,XML是描述配置的主要方式,在Spring的名義下,我們創(chuàng)建了無數(shù)行XML代碼。在一定程度上,Spring成為了XML的同義詞。
現(xiàn)在隨著強(qiáng)大的自動化配置和Java代碼的配置出現(xiàn),XML不再是唯一選擇,也不應(yīng)該是首選,學(xué)習(xí)XML配置,更多用于維護(hù)已有的XML的配置。下面話不多說了,來一起看看詳細(xì)的介紹吧。
創(chuàng)建XML配置規(guī)范
在使用XML配置前,需要創(chuàng)建一個新的配置規(guī)范,就像JavaConfig需要我們創(chuàng)建帶有 @Configuration注解的類,而在XML配置中,需要創(chuàng)建一個新的XML配置文件,并且要以<beans>元素為根。
1
2
3
4
5
6
7
8
9
|
<? xml version = "1.0" encoding = "UTF-8" ?> < beans xmlns = "http://www.springframework.org/schema/beans" ; xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" ; xmlns:context = "http://www.springframework.org/schema/context" ; xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context"> </ beans > |
可以看出基本的XML配置就已經(jīng)比JavaConfig復(fù)雜很多。用來裝配bean的最基本的XML元素包含在spring-beans模式中,在上面這個XML文件中,它被定義為根命名空間。<beans>是該模式中過的一個元素,它是所有Spring配置文件的根元素。
聲明一個簡單的<bean>
使用spring-beans模式中的另外一個元素:<bean>,該元素類似于JavaConfig中的 @Bean注解。
1
|
<bean class = "soundsystem.SgtPeppers" /> |
因為沒有明確的給定ID,所以這個bean會根據(jù)全限定類名來進(jìn)行命名。在本例中bean的ID將會是“soundsystem.SgtPeppers#0
”。其中,“#0”是一個計數(shù)的形式,用來區(qū)別相同類型的其它bean。如果再有一個就是“#1”。
盡管自動話的bean命名方式方便,但是稍引用就會認(rèn)為自動產(chǎn)生的名字就沒有多大的用處了。因此最好的辦法還是用id屬性,為每個bean設(shè)置一個自己的選擇的名字:
1
|
<bean id= "compactDisc" class = "soundsystem.SgtPeppers" /> |
可以看出XML中不再需要直接負(fù)責(zé)創(chuàng)建SgtPeppers的實例,在基于JavaConfig的配置中,我們需要自己實例化。當(dāng)Spring發(fā)現(xiàn)這個<bean>元素時,默認(rèn)調(diào)用SgtPeppers默認(rèn)的構(gòu)造器來創(chuàng)建bean。
借助構(gòu)造器注入初始化bean
在Spring XML配置中,只有一種聲明bean的方式:使用元素并指定Class屬性。在XML中聲明ID是,會有多種配置方案,具體到構(gòu)造器的注入,分為兩個基本的配置方案:
- <constructor-arg>元素
- 使用spring 3.0所引入的c-命名空間
構(gòu)造器注入bean引用,現(xiàn)在我們已經(jīng)聲明了compactDisc bean,并且SgtPeppers類實現(xiàn)了compactDisc接口,所以實際上我們已經(jīng)有了一個可以注入到CDPlayer bean中的bean。我們所需要做的就是在XML中聲明CDPlayer并通過ID引用compactDisc:
1
2
3
|
<bean id= "cdPlayer" class = "CDPlayer" > <constructor-arg ref= "compactDisc" /> </bean> |
作為替代的方案,也可以使用Spring的c-命名空間。c-命名空間是在Spring 3.0中引入的,它是在XML中更為簡潔的描述構(gòu)造器參數(shù)的方式。要使用它的話,需要在XML的頂部聲明其模式:
1
2
3
4
5
6
7
8
|
<? xml version = "1.0" encoding = "UTF-8" ?> < beans xmlns="http://www.springframework.org/schema/beans”; xmlns:c=“http://www.springframework.org/shcema/c" 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"> </ beans > |
在這之后我們就可以它來聲明構(gòu)造器的參數(shù)了,如下:
1
2
3
|
<bean id= "cdPlayer" class = "CDPlayer" > <c:cd-ref= "compactDisc" /> </bean> |
很顯然c-命名空間的方式簡練很多。具體看下寫法,“c:“表示c-命名空間的前綴,“cd”表示構(gòu)造器參數(shù)名(忘記的可以看下:Spring裝配Bean之組件掃描和自動裝配),“-ref“表示注入bean引用。
這里的cd直接引用了構(gòu)造器參數(shù)的名稱,可以利用參數(shù)在整個參數(shù)列表中的位置信息作為替代方案實現(xiàn)。
1
2
3
|
<bean id= "cdPlayer" class = "CDPlayer" > <c:_0-ref= "compactDisc" /> </bean> |
這個c-命名空間表示方法看起來比上面的更加怪異,我們將參數(shù)名用“0”表示,也就是參數(shù)的索引。因為XML中不允許數(shù)字作為第一個字符,所以用下劃線作為前綴。使用索引來標(biāo)識構(gòu)造器參數(shù)感覺比使用名字更好一些,只要保存相同的順序,就可以隨意重命名參數(shù)名,如果有多個構(gòu)造參數(shù),這個方式更有用處。因為現(xiàn)在就一個參數(shù),甚至可以不用標(biāo)識。
1
2
3
|
<bean id= "cdPlayer" class = "CDPlayer" > <c:_-ref= "compactDisc" /> </bean> |
這將是最怪異的表示方法。
將字面量注入到構(gòu)造器中
前面我們所做的DI通常指的是類型的裝配,也就是將對象的引用裝配到依賴于它的其它對象中,而有時需要引入的只是一個字面量的配置對象。現(xiàn)在需要創(chuàng)建一個新的CompactDisc實現(xiàn):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
package soundsystem; public class BlankDisc implements CompactDisc { private String title; private String artist; public BlankDisc(String title, String artist) { this .title = title; this .artist = artist; } public void play() { System.out.println( "Playing " + title + " by " + artist); } } |
在SgtPeppers中,參數(shù)都是硬編碼的,但是這個CompactDisc實現(xiàn)不同,所以XML配置也會不同:
1
2
3
4
|
<bean id= "compactDisc" class = "soundsystem.BlankDisc" > <constructor-arg value= "Sgt. Pepper's Lonely Hearts Club Band" /> <constructor-arg value= "The Beatles" /> </bean> |
我們再次用<constructor-arg>元素進(jìn)行構(gòu)造器參數(shù)的注入。但是這次我們沒有使用“ref”屬性,而是使用了value屬性,通過該屬性表明給定的要以字面量的形式注入到構(gòu)造器中。
下面用c-命名空間的方式實現(xiàn):
1
2
3
4
|
<bean id= "compactDisc" class = "soundsystem.BlankDisc" > <c:_title= "Sgt. Pepper's Lonely Hearts Club Band" /> <c:_artist= "The Beatles" /> </bean> |
可以看出,裝配字面量與裝配引用的區(qū)別在于屬性名中去掉了“-ref“的后綴。與之類似,用參數(shù)索引實現(xiàn)方式:
1
2
3
4
|
<bean id= "compactDisc" class = "soundsystem.BlankDisc" > <c:_0= "Sgt. Pepper's Lonely Hearts Club Band" /> <c:_1= "The Beatles" /> </bean> |
在裝配bean引用和字面量值方面,兩種實現(xiàn)方式的功能是相同的。但是有一種情況是<constructor-arg>能夠?qū)崿F(xiàn),c-命名空間卻無法做到。
裝配集合
假設(shè)BlankDisc構(gòu)造函數(shù)中新增一個List類型的參數(shù),如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
package soundsystem; import java.util.List; import soundsystem.CompactDisc; public class BlankDisc implements CompactDisc { private String title; private String artist; private List<String> tracks; public BlankDisc(String title, String artist, List<String> tracks) { this .title = title; this .artist = artist; this .tracks = tracks; } public void play() { System.out.println( "Playing " + title + " by " + artist); for (String track : tracks) { System.out.println( "-Track: " + track); } } } |
在聲明bean的時候,我們必須要提前準(zhǔn)備一個列表,最簡單的方式就是直接設(shè)置為null。
1
2
3
4
5
|
<bean id= "compactDisc" class = "soundsystem.BlankDisc" > <constructor-arg value= "Sgt. Pepper's Lonely Hearts Club Band" /> <constructor-arg value="The Beatles”/> <constructor-arg>< null /><constructor-arg> </bean> |
<null/>元素所做的事情,就是將null作為參數(shù)傳遞到構(gòu)造器,但這并不是解決問題的辦法,雖然在注入器能夠正常執(zhí)行,但是調(diào)用play()
方法的時候,就會出現(xiàn)異常。
合理的處理方案,我們可以利用元素將其聲明為一個列表:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
<bean id= "compactDisc" class = "soundsystem.BlankDisc" > <constructor-arg value= "Sgt. Pepper's Lonely Hearts Club Band" /> <constructor-arg value= "The Beatles" /> <constructor-arg> <list> <value>Sgt. Pepper's Lonely Hearts Club Band</value> <value>With a Little Help from My Friends</value> <value>Lucy in the Sky with Diamonds</value> <value>Getting Better</value> <value>Fixing a Hole</value> </list> </constructor-arg> </bean> |
其中,<list>元素是<constructor-arg>的子元素,這表明一個包含值的列表將會傳遞到構(gòu)造器中。其中,<value>表示每個元素。與之類似,我們可以用代替<value>,實現(xiàn)bean引用列表的裝配。
在裝配集合方面,<constructor-arg>比c-命名空間的屬性更具優(yōu)勢,目前使用c-命名空間的方式不能實現(xiàn)裝配集合的功能。
設(shè)置屬性
前面所有類完全是通過構(gòu)造器注入的,沒有使用屬性的Setter方法,下面我們看下使用Spring XML實現(xiàn)屬性注入。假設(shè)屬性注入CDPlayer如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
package soundsystem; import org.springframework.beans.factory.annotation.Autowired; import soundsystem.CompactDisc; import soundsystem.MediaPlayer; public class CDPlayer implements MediaPlayer { private CompactDisc compactDisc; @Autowired public void setCompactDisc(CompactDisc compactDisc) { this .compactDisc = compactDisc; } public void play() { compactDisc.play(); } } |
這里有個需要考慮的問題,到底是構(gòu)造器注入還是屬性注入呢?作為一個通用的規(guī)則,對強(qiáng)依賴使用構(gòu)造依賴,而可選的依賴使用屬性注入。之前的BlankDisc屬于強(qiáng)依賴,因此構(gòu)造器注入是正確的方案。不過對于CDPlayer來說,對CompactDisc的依賴不能是強(qiáng)依賴的,因為即便沒有把CompactDisc裝入進(jìn)去,CDPlayer依然具有某些功能。
因此這樣是可行的:
1
|
<bean id= "cdPlayer" class = "soundsysten.CDPlayer" /> |
在創(chuàng)建bean的時候不會出現(xiàn)任何的問題,但是CDPlayer開始工作的時候就會出現(xiàn)異常。此時,我們可以注入CDPlayer的compactDisc屬性。
1
2
3
|
<bean id= "cdPlayer" class = "soundsystem.CDPlayer" > <property name= "compactDisc" ref= "compactDisc" /> </bean> |
<property>元素為屬性的Setter方法所提供的功能,和<constructor-arg>元素為構(gòu)造器所提供的功能是一樣的。在本例中,它引入了ID為compactDisc的bean(通過ref屬性),并將其注入到compactDisc屬性中。
同樣的Spring為<property>提供了簡介的p-命名空間的替代方案。引入p-命名空間:
1
2
3
4
5
6
7
|
<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”> </beans> |
使用p-命名空間,裝配compactDisc屬性:
1
2
3
|
<bean id= "cdPlayer" class = "soundsystem.CDPlayer" p:compactDisc-ref= "compactDisc" /> |
命名空間中屬性所遵循的命名約定與c-命名空間中的屬性類似。
將字面量注入到屬性中
屬性也可以注入字面量,這與構(gòu)造器參數(shù)非常類似。我們將BlankDisc bean,通過屬性注入的方式進(jìn)行配置,而不是構(gòu)造器的方式:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
package soundsystem; import java.util.List; import soundsystem.CompactDisc; public class BlankDisc implements CompactDisc { private String title; private String artist; private List<String> tracks; public void setTitle(String title) { this .title = title; } public void setArtist(String artist) { this .artist = artist; } public void setTracks(List<String> tracks) { this .tracks = tracks; } public void play() { System.out.println( "Playing " + title + " by " + artist); for (String track : tracks) { System.out.println( "-Track: " + track); } } } |
現(xiàn)在它不在是強(qiáng)制要求我們裝配任何屬性。
1
|
<bean id= "reallyBlankDisc" class = "soundsystem.BlankDisc" /> |
當(dāng)然在裝配的時候不設(shè)置這些屬性,CD播放的時候不能正常播放,所以還是通過<property>元素的value屬性實現(xiàn)屬性注入。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<bean id= "compactDisc" class = "soundsystem.BlankDisc" > <property name= "title" value= "Sgt. Pepper's Lonely Hearts Club Band" /> <property name= "artist" value= "The Beatles" /> <property name= "tracks" > <list> <value>Sgt. Pepper's Lonely Hearts Club Band</value> <value>With a Little Help from My Friends</value> <value>Lucy in the Sky with Diamonds</value> <value>Getting Better</value> <value>Fixing a Hole</value> </list> </property> </bean> |
可以看出與之前<constructor-arg>元素裝配tracks是完全一樣的。另一種可選方案是p-命名空間的屬性來實現(xiàn):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<bean id= "compactDisc" class = "soundsystem.BlankDisc" p:title= "Sgt. Pepper's Lonely Hearts Club Band" p:artist= "The Beatles" > <property name= "tracks" > <list> <value>Sgt. Pepper's Lonely Hearts Club Band</value> <value>With a Little Help from My Friends</value> <value>Lucy in the Sky with Diamonds</value> <value>Getting Better</value> <value>Fixing a Hole</value> <value>She's Leaving Home</value> <value>Being for the Benefit of Mr. Kite!</value> <value>Within You Without You</value> <value>When I'm Sixty-Four</value> <value>Lovely Rita</value> <value>Good Morning Good Morning</value> <value>Sgt. Pepper's Lonely Hearts Club Band (Reprise)</value> <value>A Day in the Life</value> </list> </property> </bean> |
與c-命名空間一樣,裝配bean引用與裝配字面量的唯一區(qū)別在于是否帶有“-ref”后綴,同樣的p-命名空間也沒有實現(xiàn)裝配集合的功能。
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對服務(wù)器之家的支持。
原文鏈接:http://www.cnblogs.com/wxw16/p/7705219.html