Spring 從兩個角度實現自動化裝配:spring
CD 爲咱們闡述依賴注入是如何運行的。若是你不將CD插入(注入)到CD播放器中,那麼CD播放器沒有什麼太大用處。因此,能夠說,CD播放器依賴於CD才能完成它的使命。
首先,咱們定義一個CD的概念,一個接口:數組
package soundsystem; public interface CompactDisc { void play(); }
做爲接口,它定義了CD播放器對一盤CD所能進行的操做。咱們如今還須要一個實現類。安全
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 註解。
@Component:這個註解代表該類回座位組件類,並告知Spring要爲這個類建立bean。ide
不過,組件掃描默認是不啓用的。咱們還須要顯示配置一下spring,從而命令它去尋找帶有@Component註解的類,併爲其建立bean。測試
package soundsystem; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration @ComponentScan public class CDPlayerConfig { }
CDPlayerConfig類並無顯示地聲明任何bean,只不過它使用了@ComponentScan註解,這個註解可以在Spring中啓用組件掃描。若是沒有其餘配置的話,@ComponentScan默認會掃描與配置類相同的包。
測試類作一個簡單的測試。this
package soundsystem; import static org.junit.Assert.*; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes=CDPlayerConfig.class) public class CDPlayerTest { @Autowired private CompactDisc cd; @Test public void cdShouldNotBeNull() { assertNotNull(cd); } }
註解 @ContextConfiguration 會告訴它須要在 CDPlayerConfig 中加載配置。由於 CDPlayerConfig 類中包含了 @ComponentScan ,所以最終的應用上下文中應該包含 CompactDisc bean。code
Spring應用上下文中全部的bean都會給定一個ID。默認爲會根據類名指定一個ID,也就是將類名的首字母變爲小寫。若是想單獨設置ID能夠在後追加名稱對象
@Component("xxxxxx")
咱們沒有爲 @ComponentScan 設置任何屬性,按照默認規則,它會以配置類所在的包做爲基礎包(base package)來掃描組件,若是咱們想掃描不一樣的包,咱們能夠在 @ComponentScan 的 value 屬性中指明包的名稱:接口
@Configuration @ComponentScan("soundsystem") public class CDPlayerConfig {}
若是你想更加清晰地代表你所設置的死基礎包,那麼你能夠經過 basePackages 屬性進行配置:get
@Configuration @ComponentScan(basePackages="soundsystem") public class CDPlayerConfig {}
basePackages 屬性使用的複數形式,因此咱們能夠設置多個基礎包,只須要將 basePackages 屬性設置爲要掃描包的一個數組便可:
@Configuration @ComponentScan(basePackages={"soundsystem", "video"}) public class CDPlayerConfig {}
上面的例子是以 String 類型表示的。顯然這種方法是不安全的,若是重構代碼的話,那麼所指定的基礎包可能就會出現錯誤。因此咱們可使用另一種方法,將其指定爲包中鎖包含的類或接口:
@Configuration @ComponentScan(basePackageClasses={CDPlayer.class, DVDPlayer.class}) public class CDPlayerConfig {}
其實最好的方法,能夠考慮在包中建立一個用來進行掃描的空標記接口,依然可以保持對重構友好的接口引用,可是能夠避免引用任何實際的應用程序代碼。
在你的應用程序中,若是全部對象都是獨立的,彼此之間沒有任何依賴,那麼你所須要的就只是組件掃描而已。可是,不少對象會依賴其餘的對象才能完成任務。這樣的話,咱們就須要一種方法可以將組件掃描獲得的 bean 和它們的依賴裝配在一塊兒。也就是自動裝配。
簡單來講,自動裝配就是讓Spring自動知足bean依賴的一種方法,在知足依賴的過程當中,會在Spring應用上下文中尋找匹配某個bean需求的其餘bean。爲了聲明要進行自動裝配,咱們能夠藉助Spring的 @Autowired 註解。
package soundsystem; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class CDPlayer implements MediaPlayer { private CompactDisc cd; @Autowired public CDPlayer(CompactDisc cd) { this.cd = cd; } public void play() { cd.play(); } }
在構造器上加註解,代表當 Spring 建立 CDPlayer bean的時候,會經過這個構造器來進行實例化而且會傳入一個可設置給 CompactDisc 類型的bean。
無論是構造器、Setter 方法仍是其餘的方法,Spring 都會嘗試知足方法參數上所聲明的依賴。假若有且只有一個bean匹配依賴需求的話,那麼這個bean將會被裝配進來。