1. 程式人生 > >Spring實戰之裝配Bean

Spring實戰之裝配Bean

簡單 OS 屬性 值傳遞 有一個 通過 獨立 autowire 尋找

1.1Spring配置的可選方案

Spring容器負責創建應用程序中的bean並通過DI來協調這些對象之間的關系。但是,作為開發人員,你需要告訴Spring要創建哪些bean並且如何將其裝配在一起。當描述bean如何進行裝配

時,Spring具有非常大的靈活性,它提供了三種主要的裝配機制:

1.在XML中進行顯式配置。
2.在Java中進行顯式配置。
3.隱式的bean發現機制和自動裝配

1.2 自動化裝配bean

*組件掃描(component scanning):Spring會自動發現應用上下文中所創建的bean。

*自動裝配(autowiring):Spring自動滿足bean之間的依賴。

組件掃描和自動裝配組合在一起就能發揮出強大的威力,它們能夠將
你的顯式配置降低到最少。

1.3帶有@Component註解的CompactDisc實現類SgtPeppers

技術分享圖片

需要註意的就是SgtPeppers類上使用了@Component註解。這個簡的註解表明該類會作為組件類,並告知Spring要為這個類創建bean。沒有必要顯式配置SgtPeppersbean,因為這個類使用了

@Component註解,所以Spring會為你把事情處理妥當。不過,組件掃描默認是不啟用的。我們還需要顯式配置一下Spring,從而命令它去尋找帶有@Component註解的類,並為其創建bean

  

程序清單2.3的配置類展現了完成這項任務的最簡潔配置。

技術分享圖片

不過,現在我們只需觀察一下CDPlayerConfig類並沒有顯式地聲明任何bean,只不過它使用了@ComponentScan註解,這個註解能夠在Spring中啟用組件掃描。如果沒有其他配置的話,@ComponentScan默認會掃描與配置類相同的包。因為CDPlayerConfig類位於soundsystem包中,因此Spring將會掃描這個包以及這個包下的所有子包,查找帶有@Component註解的類。這樣的話,就能發現CompactDisc,並

且會在Spring中自動為其創建一個bean。

如果你更傾向於使用XML來啟用組件掃描的話,那麽可以使用Spring context命名空間的<context:component-scan>元素。程序清單2.4展示了啟用組件掃描的最簡潔XML配置。

技術分享圖片

1.4Spring的測試啟動

技術分享圖片

註解@ContextConfiguration會告訴它需要在CDPlayerConfig中加載配置。因為CDPlayerConfig類中包含了@ComponentScan,因

此最終的應用上下文中應該包含CompactDiscbean。

1.5為組件掃描的bean命名

Spring應用上下文中所有的bean都會給定一個ID。在前面的例子中,盡管我們沒有明確地為SgtPeppersbean設置ID,但Spring會根據類名為其指定一個ID。具體來講,這個bean所給定的ID為sgtPeppers,也就是將類名的第一個字母變為小寫。如果想為這個bean設置不同的ID,你所要做的就是將期望的ID作為值傳遞給@Component註解。比如說,如果想將這個bean標識為lonelyHeartsClub,那麽你需要將SgtPeppers類的@Component註解配置為如下所示:

技術分享圖片

還有另外一種為bean命名的方式,這種方式不使用@Component註解,而是使用Java依賴註入規範(Java Dependency Injection)中所提

供的@Named註解來為bean設置ID:

技術分享圖片

Spring支持將@Named作為@Component註解的替代方案。兩者之間有一些細微的差異,但是在大多數場景中,它們是可以互相替換的。

話雖如此,我更加強烈地喜歡@Component註解,而對於@Named…

1.6設置組件掃描的基礎包

為了指定不同的基礎包,你所需要做的就是在@ComponentScan的value屬性中指明包的名稱:

技術分享圖片

如果你想更加清晰地表明你所設置的是基礎包,那麽你可以通過basePackages屬性進行配置

技術分享圖片

可能你已經註意到了basePackages屬性使用的是復數形式。如果你揣測這是不是意味著可以設置多個基礎包,那麽恭喜你猜對了。如果想要這麽做的話,只需要將basePackages屬性設置為要掃描包

的一個數組即可:

技術分享圖片

@ComponentScan還提供了另外一種方法,那就是將其指定為包中所包含的類或接口:

技術分享圖片

可以看到,basePackages屬性被替換成了basePackageClasses。同時,我們不是再使用String類型的名稱來指定包,為basePackageClasses屬性所設置的數組中包含了類。這些類所在的包將會作為組件掃描的基礎包。盡管在樣例中,我為basePackageClasses設置的是組件類,但是你可以考慮在包中創建一個用來進行掃描的空標記接口(markernterface)。通過標記接口的方式,你依然能夠保持對重構友好的接口引用,但是可以避免引用任何實際的應用程序代碼(在稍後重構中,這些應用代碼有可能會從想要掃描的包中移除掉)。

在你的應用程序中,如果所有的對象都是獨立的,彼此之間沒有任何依賴,就像SgtPeppersbean這樣,那麽你所需要的可能就是組件掃描而已。但是,很多對象會依賴其他的對象才能完成任務。這樣的話,我們就需要有一種方法能夠將組件掃描得到的bean和它們的依賴裝配在一起。要完成這項任務,我們需要了解一下Spring自動化配置的另外一方面內容,那就是自動裝配。

1.7通過為bean添加註解實現自動裝配

簡單來說,自動裝配就是讓Spring自動滿足bean依賴的一種方法,在滿足依賴的過程中,會在Spring應用上下文中尋找匹配某個bean需求的其他bean。為了聲明要進行自動裝配,我們可以借助Spring的@Autowired註解。比方說,考慮程序清單2.6中的CDPlayer類。它的構造器上添加了@Autowired註解,這表明當Spring創建CDPlayerbean的時候,會通過這個構造器來進行實例化並且會傳入一個可設置給

CompactDisc類型的bean。

@Autowired註解可以用在類的任何方法上。假設CDPlayer類有一個insertDisc()方法,那麽@Autowired能夠像在setCompactDisc()上那樣,發揮完全

相同的作用:

技術分享圖片

如果沒有匹配的bean,那麽在應用上下文創建的時候,Spring會拋出一個異常。為了避免異常的出現,你可以將@Autowired的required屬性設置為false:

將required屬性設置為false時,Spring會嘗試執行自動裝配,但是如果沒有匹配的bean的話,Spring將會讓這個bean處於未裝配的狀態。但是,把required屬性設置為false時,你需要謹慎對待。如果在你的代碼中沒有進行null檢查的話,這個處於未裝配狀態的屬性有可能會出現NullPointerException。

@Autowired是Spring特有的註解。如果你不願意在代碼中到處使用Spring的特定註解來完成自動裝配任務的話,那麽你可以考慮將其替換為@Inject:

技術分享圖片

@Inject註解來源於Java依賴註入規範,該規範同時還為我們定義了@Named註解。在自動裝配中,Spring同時支持@Inject和@Autowired。盡管@Inject和@Autowired之間有著一些細微的差別,但是在大多數場景下,它們都是可以互相替換的。在@Inject和@Autowired中,我沒有特別強烈的偏向性。實際上,在有的項目中,我會發現我同時使用了這兩個註解。不過在本書的樣例中,我會一直使用@Autowired,而你可以根據自己的情況,選擇其中的任意一個。

Spring實戰之裝配Bean