Spring裝配bean基礎(chǔ)

Spring容器負(fù)責(zé)創(chuàng)建應(yīng)用程序中的bean并通過DI來協(xié)調(diào)這些對象之間的關(guān)系,我們需要做的就是告訴Spring要創(chuàng)建哪些bean以及這些bean的依賴情況岁经。
Spring提供了三種主要的裝配機制,選擇哪種方案很大程度上就是個人喜好的問題缀壤,你盡可以選擇自己最喜歡的方式纠亚。

1.隱式的bean發(fā)現(xiàn)機制和自動裝配

Spring從兩個角度來實現(xiàn)自動化裝配:

  • 組件掃描(component scanning):Spring會自動發(fā)現(xiàn)應(yīng)用上下文中所創(chuàng)建的bean。
  • 自動裝配(autowiring):Spring自動滿足bean之間的依賴蒂胞。
    ?首先,定義一個接口:
package soundsystem;
public interface CompactDisc {
        void play{};
}

以及蛤织,CompactDisc實現(xiàn)類SgtPeppers:

package soundsystem;
import org.springframework.stereotype.Component;
@Component("LonelyHeartsClub")  // or @Named
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)建一個id為LonelyHeartsClub的bean姚炕。不過,組件掃描默認(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 { 
}

CDPlayerConfig使用了@Configuration注解,表明這是一個spring的配置類松逊,而@ComponentScan注解則能夠在Spring中啟用組件掃描功能。如果沒有其他配置的話经宏,@ComponentScan默認(rèn)會掃描與配置類相同的包驯击。因為CDPlayerConfig類位于soundsystem包中烁兰,因此Spring將會掃描這個包以及這個包下的所有子包徊都,查找?guī)в蠤Component注解的類。這樣的話碟贾,就能發(fā)現(xiàn)CompactDisc,并且會在Spring中自動為其創(chuàng)建一個bean袱耽。如果你想要將config類放入一個獨立的包中以方便管理,也可以為@ComponentScan傳入你想要作為掃描基礎(chǔ)包的包名史翘,如:

 @ComponentScan("org.xxx.packagename")

或者

@ComponentScan(basePackages={"org.xxx.packagename","org.xxx.otherpackagename"})

來指定多個基礎(chǔ)包琼讽。
?為了以后方便重構(gòu)(有可能改變包名),那么可以采用更加安全的方式

   @ComponentScan(basePackageClasses={abc.class, 123.class})

不再使用String類型的名稱來指定包钻蹬,為basePackageClasses屬性所設(shè)置的數(shù)組中包含了類。這些類所在的包將會作為組件掃描的基礎(chǔ)包问欠。
?如果你更傾向于使用XML來啟用組件掃描的話,那么可以使用Spring context命名空間的<context:component-scan>元素顺献。

   <?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:mvc="http://www.springframework.org/schema/mvc"
  xmlns:context="http://www.springframework.org/schema/context"   xmlns:aop="http://www.springframework.org/schema/aop"
     xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

   <context:component-scan base-package="package" />

顯然注整,在實際的項目開發(fā)中能曾,bean之間的關(guān)系不會像上文所列舉的那樣簡單肿轨,不同的組件往往相互依賴來完成復(fù)雜的任務(wù),所以椒袍,我們需要了解一下Spring自動化配置的另外一方面內(nèi)容,那就是自動裝配槐沼。
?通過自動裝配捌治,將一個CD注入到CDPlayer之中:

   package soundsystem;
   import org.springframework.beans.factory.annotation.Autowired;
   import org.springframework.stereotype.Component;

   @Component // or @Named
   public class CDPlayer implements MediaPlayer {
     private CompactDisc cd;

     @Autowired // or @Inject
     public CDPlayer(CompactDisc cd) {
       this.cd = cd;
     }

     public void play() {
       cd.play();
     }
   }

構(gòu)造器上添加了@Autowired注解,這表明當(dāng)Spring創(chuàng)建CDPlayer bean的時候肖油,會通過這個構(gòu)造器來進(jìn)行實例化并且會傳入一個實現(xiàn)了CompactDisc的bean。
?@Autowired注解不僅能夠用在構(gòu)造器上森枪,還能用在類的任何方法上。比如說县袱,如果CDPlayer有一個insertDisc()方法,那么可以采用如下的注解形式進(jìn)行自動裝配:

   @Autowired
   public insertDisc(CompactDisc cd) {
       this.cd = cd;
   }

如果沒有匹配的bean筋遭,那么在應(yīng)用上下文創(chuàng)建的時候,Spring會拋出異常漓滔。為了避免異常的出現(xiàn)编饺,你可以將@Autowired的required屬性設(shè)置為false:

   @Autowired(required=false)
   public insertDisc(CompactDisc cd) {
       this.cd = cd;
   }

將required屬性設(shè)置為false時响驴,Spring會嘗試執(zhí)行自動裝配,但是如果沒有匹配的bean的話豁鲤,Spring將會讓這個bean處于未裝配的狀態(tài)。但是养距,把required屬性設(shè)置為false時,你需要謹(jǐn)慎對待棍厌。如果在你的代碼中沒有進(jìn)行null檢查的話,這個處于未裝配狀態(tài)的屬性有可能會出現(xiàn)NullPointerException耘纱。

2.通過Java代碼裝配bean

大部分情況下組件掃描和自動裝配實現(xiàn)Spring的自動化配置是更為推薦的方式毕荐,但有時候自動化配置的方案行不通時,比如說憎亚,你想要將第三方庫中
的組件裝配到你的應(yīng)用中第美,在這種情況下,是沒有辦法在它的類上添加@Component和@Autowired注解的扳缕,因此就不能使用自動化裝配的方案了别威。

讓我們修改一下CDPlayerConfig類:

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

   @Configuration
   public class CDPlayerConfig { 
   }

我們?nèi)サ袅薂ComponentScan注解省古,意味著spring容器不再自動掃描我們帶有@Component(或@Named)注解的類了衫樊,下面我們將在CDPlayerConfig類中顯式地配置之前創(chuàng)建的類利花。
?我們在config類中加入以下代碼:

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

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

@Bean注解會告訴Spring這個方法將會返回一個對象炒事,該對象要注冊為Spring應(yīng)用上下文中的bean蔫慧。方法體中包含了最終產(chǎn)生bean實例的邏輯。bean的名字默認(rèn)為方法名睡扬,如有需要黍析,可以使用如下方法修改:

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

使用java配置類進(jìn)行裝配同樣要考慮依賴注入的問題阐枣,下面就是一種聲明CDPlayer的可行方案:

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

看起來,cdPlayer所依賴的CompactDisc是通過調(diào)用sgtPeppers()得到的甩鳄,但情況并非完全如此额划。因為sgtPeppers()方法上添加了@Bean注解,Spring將會攔截所有對它的調(diào)用揖赴,并確保直接返回該方法所創(chuàng)建的bean抑胎,而不是每次都對其進(jìn)行實際的調(diào)用,也就是說sgtPeppers仍然是單例的。
?但是上面的寫法有一個不足盆昙,那就是如果sgtPeppers()方法沒有定義在CDPlayerConfig中焊虏,而是定義在另一個config或xml配置文件中,cdPlayer方法是無法調(diào)用的炼团,所以,這種方式并不合理易桃,來看另一種方法:

   @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方法。

再次強調(diào)一遍史飞,帶有@Bean注解的方法可以采用任何必要的Java功能來產(chǎn)生bean實例仰税。

3.通過XML裝配bean

// TODO

4.解決不同配置方式之間的依賴關(guān)系

現(xiàn)在,我們已經(jīng)知道cdPlayer bean需要依賴于compactDisc bean吐绵,假如我們的cdPlayer bean依然由CDPlayerConfig來裝配河绽,而compactDisc bean則改由CDConfig來裝配:

   package soundsystem;

   import org.springframework.context.annotation.Bean;
   import org.springframework.context.annotation.Configuration;

   @Configuration
   public class CDConfig {
     @Bean
     public CompactDisc compactDisc() {
       return new SgtPeppers();
     }
   }

一種方法就是在CDPlayerConfig中使用@Import注解導(dǎo)入CDConfig:

   package soundsystem;
   import org.springframework.context.annotation.Configuration;
   import org.springframework.context.annotation.Import;
   import org.springframework.context.annotation.Bean;

   @Configuration
   @Import(CDConfig.class)
   public class CDPlayerConfig { 
       @Bean
       public CDPlayer cdPlayer(CompactDisc  compactDisc ) {
            return new CDPlayer(compactDisc );
       }
   }

或者采用一個更好的辦法耙饰,也就是不在CDPlayerConfig中使用@Import,而是創(chuàng)建一個更高級別的SoundSystemConfig廷痘,在這個類中使用@Import將兩個配置類組合在一起:

package soundsystem;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;

@Configuration
@Import({CDPlayerConfig.class, CDConfig.class})
public class SoundSystemConfig {

}

同樣的笋额,假如還有一部分bean定義在bean-config.xml中,則需要用@ImportResource注解導(dǎo)入:

package soundsystem;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.ImportResource;

@Configuration
@Import({CDPlayerConfig.class, CDConfig.class})
@ImportResource("classpath:bean-config.xml")
public class SoundSystemConfig {

}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末昨寞,一起剝皮案震驚了整個濱河市厦滤,隨后出現(xiàn)的幾起案子掏导,更是在濱河造成了極大的恐慌,老刑警劉巖添瓷,帶你破解...
    沈念sama閱讀 211,639評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件值纱,死亡現(xiàn)場離奇詭異虐唠,居然都是意外死亡,警方通過查閱死者的電腦和手機疆偿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,277評論 3 385
  • 文/潘曉璐 我一進(jìn)店門杆故,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人饲趋,你說我怎么就攤上這事撤蟆》憬” “怎么了敷鸦?”我有些...
    開封第一講書人閱讀 157,221評論 0 348
  • 文/不壞的土叔 我叫張陵寝贡,是天一觀的道長圃泡。 經(jīng)常有香客問我愿险,道長,這世上最難降的妖魔是什么风秤? 我笑而不...
    開封第一講書人閱讀 56,474評論 1 283
  • 正文 為了忘掉前任缤弦,我火速辦了婚禮彻磁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘累提。我一直安慰自己磁浇,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,570評論 6 386
  • 文/花漫 我一把揭開白布鳍贾。 她就那樣靜靜地躺著交洗,像睡著了一般构拳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上斗埂,一...
    開封第一講書人閱讀 49,816評論 1 290
  • 那天凫海,我揣著相機與錄音,去河邊找鬼行贪。 笑死漾稀,一個胖子當(dāng)著我的面吹牛崭捍,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播殷蛇,決...
    沈念sama閱讀 38,957評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼粒梦!你這毒婦竟也來了亮航?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,718評論 0 266
  • 序言:老撾萬榮一對情侶失蹤谍倦,失蹤者是張志新(化名)和其女友劉穎塞赂,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體昼蛀,經(jīng)...
    沈念sama閱讀 44,176評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡宴猾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,511評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了叼旋。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片仇哆。...
    茶點故事閱讀 38,646評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡夫植,死狀恐怖讹剔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情详民,我是刑警寧澤延欠,帶...
    沈念sama閱讀 34,322評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站沈跨,受9級特大地震影響由捎,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜饿凛,卻給世界環(huán)境...
    茶點故事閱讀 39,934評論 3 313
  • 文/蒙蒙 一狞玛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧涧窒,春花似錦心肪、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,755評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春固该,著一層夾襖步出監(jiān)牢的瞬間碑隆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,987評論 1 266
  • 我被黑心中介騙來泰國打工蹬音, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人休玩。 一個月前我還...
    沈念sama閱讀 46,358評論 2 360
  • 正文 我出身青樓著淆,卻偏偏與公主長得像,于是被迫代替她去往敵國和親拴疤。 傳聞我的和親對象是個殘疾皇子永部,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,514評論 2 348

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)呐矾,斷路器苔埋,智...
    卡卡羅2017閱讀 134,633評論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,773評論 6 342
  • 本章內(nèi)容: 聲明Bean 構(gòu)造器注入和Setter方法注入 裝配Bean 控制bean的創(chuàng)建和銷毀 任何一個成功的...
    謝隨安閱讀 1,637評論 0 9
  • 2.1 Spring配置的可選方案 Spring提供了三種主要的裝配機制: 1)在XML中進(jìn)行顯示配置组橄。2)在ja...
    如一諾然閱讀 485評論 0 1
  • 經(jīng)常聽人說:想做就去做,別猶豫玉工,否猶則豫一會就沒了做這件事的興趣了。 我曾經(jīng)深以為是淘菩,可是隨著時間的推移遵班, 年齡的...
    第十頁閱讀 332評論 0 1