Spring 學(xué)習(xí)筆記(二)如何裝配 Bean

在Spring中蚊伞,對象無需自己查找或創(chuàng)建與其所關(guān)聯(lián)的其他對象颅停。相反,容器負(fù)責(zé)把需要相互協(xié)作的對象引用賦予各個對象。
創(chuàng)建應(yīng)用對象之間協(xié)作關(guān)系的行為通常稱為裝配(wiring)柏肪,這也是
依賴注入(DI)的本質(zhì)。
在Spring中裝配bean有多種方式谬俄。我們先花一點(diǎn)時間來介紹一下配置Spring容器最常見的三種方法。
-在XML中進(jìn)行顯式配置。
-在Java中進(jìn)行顯式配置返吻。
-隱式的bean發(fā)現(xiàn)機(jī)制和自動裝配街佑。

我的建議是盡可能地使用自動配置的機(jī)制榨婆。顯式配置越少越好谊迄。當(dāng)你必須要顯式配置bean的時候(比如,有些源碼不是由你來維護(hù)的,而當(dāng)你需要為這些代碼配置bean的時候),我推薦使用類型安全并且比XML更加強(qiáng)大的JavaConfig。最后,只有當(dāng)你想要使用便利的XML命名空間,并且在JavaConfig中沒有同樣的實(shí)現(xiàn)時,才應(yīng)該使用XML。

自動化裝配 bean

Spring從兩個角度來實(shí)現(xiàn)自動化裝配:
-組件掃描(component scanning):Spring會自動發(fā)現(xiàn)應(yīng)用上下文中所創(chuàng)建的bean惕虑。
-自動裝配(autowiring):Spring自動滿足bean之間的依賴伟叛。

我們用一個 CD 播放器來闡述如何裝配 bean:
先建立 CD 的概念紊遵。

package soundsystem;
public interface CompactDisc{
    void play();
}

再創(chuàng)建一個實(shí)現(xiàn):

package soundsystem;
import org.springframework.stereotype.Component;

@Component
public class SgtPeppers implements CompactDisc{
    private String title = "Sgt. Pepper's Lonely Hearts Club Band";
    private String artist = "The Beatles";

    public void play(){
        System.out.println("Playing" + title + "by" + artist);    
    }
}

SgtPeppers類上使用了@Component注解雹锣。這個簡單的注解表明該類會作為組件類,并告知Spring要為這個類創(chuàng)建bean癞蚕。沒有必要顯式配置SgtPeppersbean蕊爵,因?yàn)檫@個類使用了@Component注解,所以Spring會為你把事情處理妥當(dāng)桦山。
不過攒射,組件掃描默認(rèn)是不啟用的。我們還需要顯式配置一下Spring恒水,從而命令它去尋找?guī)в蠤Component注解的類会放,并為其創(chuàng)建bean。

package soundsystem;
import org.springframework.context.annotation.componentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan
public class CDPlayerConfig{
}

它使用了@ComponentScan注解钉凌,這個注解能夠在Spring中啟
用組件掃描咧最。如果沒有其他配置的話,@ComponentScan默認(rèn)會掃描與配置類相同的包御雕。因?yàn)镃DPlayerConfig類位于soundsystem包中矢沿,因此Spring將會掃描這個包以及這個包下的所有子包,查找?guī)в蠤Component注解的類酸纲。這樣的話捣鲸,就能發(fā)現(xiàn)CompactDisc,并且會在Spring中自動為其創(chuàng)建一個bean闽坡。
xml 代碼:

<?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 
http://wwww.springframework.org/schema/context/spring-context.xsd">
    
    <context:component-scan base-package="soundsystem"/>
</beans>

通過 Java 代碼裝配 bean

盡管在很多場景下通過組件掃描和自動裝配實(shí)現(xiàn)Spring的自動化配置是更為推薦的方式栽惶,但有時候自動化配置的方案行不通,因此需要明確配置Spring疾嗅。
在這種情況下外厂,你必須要采用顯式裝配的方式。在進(jìn)行顯式配置的時候代承,有兩種可選方案:Java和XML汁蝶。
創(chuàng)建配置類

package soundsystem;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CDPlayerConfig{
}

創(chuàng)建JavaConfig類的關(guān)鍵在于為其添加@Configuration注解,@Configuration注解表明這個類是一個配置類次泽,該類應(yīng)該包含在Spring應(yīng)用上下文中如何創(chuàng)建bean的細(xì)節(jié)穿仪。
生命簡單的 bean

@Bean
public CompactDisc sgtPeppers(){
    return new SgtPeppers();
}

@Bean注解會告訴Spring這個方法將會返回一個對象席爽,該對象要注冊為Spring應(yīng)用上下文中的bean意荤。方法體中包含了最終產(chǎn)生bean實(shí)例的邏輯。
可以為 bean 指定一個名字:

@Bean(name="lonelyHeartsClubBand")
public CompactDisc sgtPeppers(){
    return new SgtPeppers();
}

在JavaConfig中裝配bean的最簡單方式就是引用創(chuàng)建bean的方法只锻。例如玖像,下面就是一種聲明CDPlayer的可行方案:

@Bean
public CDPlayer cdPlayer(){
    return new CDPlayer(sgtPeppers());
}
@Bean
public CDPlayer anotherCDPlayer(){
    return new CDPlayer(sgtPeppers());
}

這里為什么創(chuàng)建了兩個 bean 是為了說明一個事情,Spring將會攔截所有對 sgtPeppers 的調(diào)用,并確保直接返回該方法所創(chuàng)建的bean捐寥,而不是每次都對其進(jìn)行實(shí)際的調(diào)用笤昨。Spring中的bean都是單例的,沒有必要創(chuàng)建完全相同的第二個實(shí)例握恳。
另一種裝配方式:

@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc){
    return new CDPlayer(compactDisc);
}

在這里瞒窒,cdPlayer()方法請求一個CompactDisc作為參數(shù)。當(dāng)Spring調(diào)用cdPlayer()創(chuàng)建CDPlayerbean的時候乡洼,它會自動裝配一個CompactDisc到配置方法之中崇裁。然后,方法體就可以按照合適的方式來使用它束昵。借助這種技術(shù)拔稳,cdPlayer()方法也能夠?qū)ompactDisc注入到CDPlayer的構(gòu)造器中,而且不用明確引用CompactDisc的@Bean方法锹雏。
Setter 方法注入:

@Bean
public CDPlayer cdPlayer(CompactDisc compactDisc){
    CDPlayer cdplayer = new CDPlayer(compactDisc);
    cdPlayer.setCompactDisc(compactDisc);
    return cdPlayer;
}

通過 XML 裝配

最為簡單的Spring XML配置如下所示:

<?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
    http://www.springframework.org/schema/context">
  <!-- configuration details go here -->
</beans>

聲明一個簡單的<bean>:

<bean class="soundsystem.SgtPeppers"/>

在本例中巴比,bean的ID將會是“soundsystem.SgtPeppers#0”。其中礁遵,“#0”是一個計數(shù)的形式轻绞,用來區(qū)分相同類型的其他bean。如果你聲明了另外一個SgtPeppers佣耐,并且沒有明確進(jìn)行標(biāo)識铲球,那么它自動得到的ID將會是“soundsystem.SgtPeppers#1”。

借助構(gòu)造器注入初始化 bean
在XML中聲明DI時晰赞,會有多種可選的配置方案和風(fēng)格稼病。具體到構(gòu)造器注入,有兩種基本的配置方案可供選擇:
-<constructor-arg>元素

  <bean id="cdPlayer"
        class="soundsystem.CDPlayer">
    <constructor-arg ref="compactDisc" />
  </bean>

-使用Spring 3.0所引入的c-命名空間

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:c="http://www.springframework.org/schema/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">

  <bean id="compactDisc" class="soundsystem.BlankDisc">
      c:cd-ref="compactDisc"/>
  </bean>
</beans>
image.png

上面這種直接引用了參數(shù)的名稱掖鱼,可以用下面方法來替代:(因?yàn)椴恢С謹(jǐn)?shù)字 所以參數(shù)標(biāo)號前面加下劃線)

<bean id="cdPlayer" class="soundsystem.CDPlayer"
    c:_0-ref="compactDisc"/>

或者不用標(biāo)志參數(shù)

<bean id="cdPlayer" class="soundsystem.CDPlayer"
    c:_-ref="compactDisc"/>

將字面量值裝配到構(gòu)造器之中:

  <bean id="compactDisc" class="soundsystem.BlankDisc">
    <constructor-arg value="Sgt. Pepper's Lonely Hearts Club Band" />
    <constructor-arg value="The Beatles" />
  </bean>

用 c 命名空間:

  <bean id="compactDisc" class="soundsystem.BlankDisc">
    <c:title="Sgt. Pepper's Lonely Hearts Club Band" />
    <c:artist="The Beatles" />
  </bean>

也可以去掉 “-ref” 后綴

  <bean id="compactDisc" class="soundsystem.BlankDisc">
    <c:_0="Sgt. Pepper's Lonely Hearts Club Band" />
    <c:_1="The Beatles" />
  </bean>

裝配集合

<?xml version="1.0" encoding="UTF-8" ?>
<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>Lucky in the Sky with Diamonds</value>
            <value>Getting Better</value>
            <value>Fixing a Hole</value>
            ......
        </list>
    </constructor-arg>
</bean>

也可以裝配 set 集合然走,就將 list 換成 set 就行了。
設(shè)置屬性
下面我們看一下如何用 xml 實(shí)現(xiàn)屬性注入戏挡,假設(shè)屬性注入的 CDPlayer 如下所示:

public class CDPlayer implements MediaPlayer {
    private CompactDisc compactDisc;
    
    @Autowired
    public void setCompactDisc(CompactDisc compactDisc){
        this.compactDisc = compactDisc;
    }
    public void play(){
        compactDisc.play();
    }
}

一般我們對強(qiáng)依賴使用構(gòu)造器注入芍瑞,而對可選性的依賴使用屬性注入。

<bean id="cdPlayer" class="soundsystem.CDPlayer">
    <property name="compactDisc" ref="compactDisc"/>
</bean>

也可以使用 p 命名空間裝配

<bean id="cdPlayer" class="soundsystem.CDPlayer" p:compactDisc-ref="compactDisc"/>

image.png

首先褐墅,屬性的名字使用了“p:”前綴拆檬,表明我們所設(shè)置的是一個屬性。接下來就是要注入的屬性名妥凳。最后竟贯,屬性的名稱以“-ref”結(jié)尾,這會提示Spring要進(jìn)行裝配的是引用逝钥,而不是字面量屑那。
將字面量注入到屬性中

  <bean id="compactDisc"
        class="soundsystem.properties.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>
        <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 id="compactDisc"
        class="soundsystem.properties.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>

注意不能用 p 命名空間裝配集合。

參考文獻(xiàn):spring in action

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市持际,隨后出現(xiàn)的幾起案子沃琅,更是在濱河造成了極大的恐慌,老刑警劉巖蜘欲,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件益眉,死亡現(xiàn)場離奇詭異,居然都是意外死亡姥份,警方通過查閱死者的電腦和手機(jī)呜叫,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來殿衰,“玉大人朱庆,你說我怎么就攤上這事∶葡椋” “怎么了娱颊?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長凯砍。 經(jīng)常有香客問我箱硕,道長,這世上最難降的妖魔是什么悟衩? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任剧罩,我火速辦了婚禮,結(jié)果婚禮上座泳,老公的妹妹穿的比我還像新娘惠昔。我一直安慰自己,他們只是感情好挑势,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布镇防。 她就那樣靜靜地躺著,像睡著了一般潮饱。 火紅的嫁衣襯著肌膚如雪来氧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天香拉,我揣著相機(jī)與錄音啦扬,去河邊找鬼。 笑死凫碌,一個胖子當(dāng)著我的面吹牛扑毡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播证鸥,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼僚楞,長吁一口氣:“原來是場噩夢啊……” “哼勤晚!你這毒婦竟也來了枉层?” 一聲冷哼從身側(cè)響起泉褐,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鸟蜡,沒想到半個月后膜赃,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡揉忘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年跳座,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片泣矛。...
    茶點(diǎn)故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡疲眷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出您朽,到底是詐尸還是另有隱情狂丝,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布哗总,位于F島的核電站几颜,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏讯屈。R本人自食惡果不足惜蛋哭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望涮母。 院中可真熱鬧谆趾,春花似錦、人聲如沸叛本。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽炮赦。三九已至怜跑,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間吠勘,已是汗流浹背性芬。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留剧防,地道東北人植锉。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像峭拘,于是被迫代替她去往敵國和親俊庇。 傳聞我的和親對象是個殘疾皇子狮暑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評論 2 345

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