在Spring中,對象無需本身查找或建立與其所關聯的其餘對象。相反,容器負責把須要相互協做的對象引用賦予各個對象。java
建立應用對象之間協做關係的行爲一般稱爲裝配(wiring),這也是依賴注入的本質。spring
Spring提供了三種主要的裝配機制:數組
做者建議儘量的使用自動裝配的機制。顯式配置越少越好,當必需要顯式配置bean的時候(好比,有些源碼不是由你來維護的,而當你須要爲這些代碼配置bean的時候),推薦使用類型安全而且比XML更增強大的JavaConfig。最後,只有當你想要使用便利的XML命名空間,而且在JavaConfig中沒有一樣的實現是才應該使用XML。安全
Spring從兩個角度實現自動化裝配:ide
在類上使用@Component註解,這個註解代表該類會做爲組件類,並告知Spring要爲這個類建立bean。測試
組件掃描默認是不啓用的,還須要顯式配置一下Spring,從而命令它去尋找帶有@Component註解的類併爲其建立bean。ui
@Configuation @ComponentScan public class CDPlayerConfig { }
若是沒有其餘配置,@ComponentScan默認會掃描與配置類相同的包。spa
若是想使用XML來啓用組件掃描,可使用Spring context命名空間的context:component-scan元素。code
<?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.springframeword.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <context:component-scan base-package="soundsystem"/> </beans>
測試組件掃描代碼:component
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes=CDPlayerConfig.class) public class CDPlayerText { @Autowired private CompactDisc cd; @Test public void cdShouldNotBeNull() { assertNotNull(cd) } }
CDPlayerTest使用了Spring的SpringJUnit4ClassRunner,以便在測試開始的時候自動建立Spring的應用上下文。註解@ContextConfiguration會告訴它須要在CDPlayerConfig中加載配置。
在組件掃描中若是沒有明確的設置ID,Spring會根據類名爲其指定一個ID。這個bean所給定的ID是首字母變爲小寫的類名。
若是想爲這個bean設置不一樣的ID,須要將其做爲值傳遞給@Component註解。
@Component("lonelyHeartsClub") public class SgtPeppers implements CompactDisc { }
另一種bean命名方式使用Java依賴注入規範中提供的@Named註解:
@Named("lonelyHeartsClub") public class SgtPeppers implements CompactDisc { }
Spring支持將@Named做爲@Component註解的替代方案。二者之間由一些細微的差別,但在大多數場景中能夠互換。
本書的做者更喜歡@Component。
若是沒有爲@ComponentScan設置屬性,按照默認規則,它會以配置類所在的包做爲基礎包來掃描逐漸。
若是想掃描不一樣的包,在@ComponentScan的value屬性中指定包名便可。
@Configuraion @ComponentScan("soundsystem") public class CDPlayerConfig{ }
若是想更加清晰的代表所設置的是基礎包,能夠經過basePackages屬性進行配置:
@Configuration @ComponentScan(basePackages="soundsystem") public class CDPlayerConfig{}
basePackages屬性能夠設置多個包,賦值一個數組便可:
@Configuration @ComponentScan(basePackages={"soundsystem", "video"}) public class CDPlayerConfig { }
除了將包設置爲簡單的String類型外,@ComponentScan哈提供了另一種方法,將其指定爲包中所包含的類或接口:
@Configuration @ComponentScan(basePackageClasses={CDPlayer.class, DVDPlayer.class}) public class CDPlayerConfig { }
能夠在構造器、setter方法、任何方法上使用@Autowired註解,Spring會嘗試知足方法參數上所聲明的依賴。假若有且只有一個bean匹配依賴需求,那麼這個bean將會被裝配進來。
若是沒有匹配的bean,那麼在應用上下文建立的時候會拋出異常。能夠將@Autowired的required屬性設置爲false,此時Spring會嘗試自動裝配,可是若是沒有匹配的bean的話該屬性將會爲null。
若是有多個bean都知足依賴關係,Spring將會拋出異常。
@Autowired是Spring特有的註解。可使用@Inject註解替代。
顯式的裝配方式有兩種:Java和XML。
@Configuration註解代表這個類是一個配置類,該類應該包含在Spring應用上下文中如何建立bean的細節。
要在JavaConfig中聲明bean,須要編寫一個方法,這個方法會建立所需類型的實例,而後給這個方法添加@Bean註解。
@Bean註解會告訴Spring這個方法將返回一個對象,該對象要註冊爲Spring應用上下文中的bean。方法體中包含了最終產生bean實例的邏輯。
默認狀況下,bean的ID與方法名一致。若是想爲其設置一個不一樣的名字,能夠重命名該方法,也能夠經過@Bean的name屬性指定。
在JavaConfig中裝配bean的最簡單方式就是引用建立bean的方法。在方法上添加了@Bean註解,Spring將會攔截全部對它的調用,並確保直接返回該方法所建立的bean,而不是每次都對其進行實際的調用。
經過調用方法引用bean的方式有點使人困惑。還有一種理解起來更簡單的方式:
@Bean public CDPlayer cdPlayer(CompactDisc compactDisc) { return new CDPlayer(compactDisc); }
cdPlaye()方法請求一個CompactDisc做爲參數,當Spring調用cdPlayer()建立CDPlayer bean的時候,它會自動裝配一個CompactDisc到配置方法之中。
經過這種方式引用其餘的bean一般是最佳的選擇,由於它不會要求將CompactDisc聲明到同一個配置類之中。在這裏甚至沒有要求CompactDisc必需要在JavaConfig中聲明,實際上它能夠經過組件掃描功能自動發現或者經過XML來進行配置。能夠將配置分散到多個配置類、XML文件以及自動掃面和裝配bean之中。
在XML配置中,要建立一個XML文件,而且要以<beans>元素爲根。
<?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.springframeword.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context"> <!-- 配置詳情 --> </beans>
<bean>元素相似於JavaConfig中的@Bean註解。
若是沒有給定ID,因此這個bean將會根據全限定類名來進行命名。例如「soundsystem.SgtPeppers#0「,其中「#0」是一個計數形式,用來區分相同類型的其餘bean。
構造器注入有兩種基本的配置方案可供選擇:
<bean id="cdPlayer" class="soundsystem.CDPlayer"> <constructor-arg ref="compactDisc"/> </bean>
c-命名空間的schema:
xmlns:c="http://www.springframework.org/schema/c"
<bean id="cdPlayer" class="soundsystem.CDPlayer" c:cd-ref="compactDisc" />
屬性以c:開頭,也就是命名空間的前綴。接下來是要裝配的構造器參數名,在此以後是-ref,這是一個命名約定,告訴Spring正在裝配的是一個bean應用。
可使用參數在整個參數列表中的位置來替代參數名:
<bean id="cdPlayer" class="soundsystem.CDPlayer" c:_0-ref="compactDisc" />
由於在XML中不容許數字做爲屬性的第一個字符,所以必需要添加一個下劃線做爲前綴。
若是隻有一個參數,不用標示參數:
<bean id="cdPlayer" class="soundsystem.CDPlayer" c:_-ref="compactDisc" />
<bean id="compactDisc" class="soundsystem.BlankDisc"> <constructor-arg value="sgt. Pepper" /> </bean>
依然使用<constructor-arg>元素進行注入,可是使用了value屬性。
<bean id="compactDisc" class="soundsystem.BlankDisc" c:_title="sgt. Pepper"/>
使用c-命名空間裝配字面量與裝配引用的區別在於屬性名中去掉了-ref後綴。
<constructor-arg>能夠將集合裝配到構造器參數重,而c-命名空間不能。
可使用<null/>元素將null傳遞給構造器。
可使用<list>元素聲明一個列表:
<constructor-arg> <list> <value>.....</value> <value>......</value> </list> </constructor-arg>
<list>元素是<constructor-arg>的子元素,這代表一個包含值的列表將會傳遞到構造器中。其中<value>元素用來指定列表中的每一個元素。
與之相似,可使用<ref>元素代替<value>,實現bean引用列表的裝配。
能夠用相同的方式使用<set>元素。<set>和<list>元素的區別不大,不管在哪一種狀況下,<set>或<list>均可以用來裝配List、Set甚至是數組。
<property>元素爲屬性的setter方法所提供的功能與<constructor-arg>元素爲構造器提供的功能是同樣的。
Spring提供了p-命名空間做爲<property>元素的替代方案。p-命名空間的schema:
xmlns:p="http://www.springframework.org/schema/p"
util-命名空間所提供的功能之一是util:list元素,它會建立一個列表的bean。
xmlns:util="http://www.springframework.org/schema/util"
<util:list id="trackList"> <value>......</value> <value>.....</value> </util:list>
下表展現了Spring util-命名空間中的元素
元素 | 描述 |
---|---|
util:constant | 引用某個類型的public static域,並將其暴露爲bean |
util:list | 建立一個java.util.List類型的bean,其中包含值或引用 |
util:map | 建立一個java.util.Map類型的bean,其中包含值或引用 |
util:properties | 建立一個java.util.Propertie類型的bean |
util:property-path | 引用一個bean的屬性(或內嵌屬性),並將其暴露爲bean |
util:set | 建立一個java.util.Set類型的bean,其中包含值或引用 |
使用@Import註解引用其餘JavaConfig配置,使用@ImportResource註解引入XML配置。
@Configuration @Import(CDPlayerConfig.class) @ImportResource("classpath:cd-config.xml") public class SoundSystemConfig { }
在XML中可使用<import>元素來引用其餘XML配置。
將JavaConfig做爲bean使用<bean>元素導入XML配置文件。