Spring容器負責建立應用程序中的bean同時經過ID來協調這些對象之間的關係。做爲開發人員,咱們須要告訴Spring要建立哪些bean而且如何將其裝配到一塊兒。java
spring中bean裝配有兩種方式spring
固然這些方式也能夠配合使用。安全
咱們測試代碼以下ide
CompactDisc和MediaPlayer是兩個接口 其中MediaPlayer的構造方法參數類型爲CompactDisc。
咱們主要測試CompactDisc和MediaPlayer的實現有沒有注入進來,同時MediaPlayer接口對於CompactDisc的依賴有沒有知足
package com.zcs; import com.zcs.service.CompactDisc; import com.zcs.service.MediaPlayer; 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; import static junit.framework.TestCase.assertEquals; import static junit.framework.TestCase.assertNotNull; @RunWith(SpringJUnit4ClassRunner.class) //XML配置 //@ContextConfiguration(locations ="spring-config.xml") //Java代碼配置 @ContextConfiguration(classes =CDPlayerConfig.class) public class CDPlayerTest { @Autowired private CompactDisc cd; @Autowired private MediaPlayer player; @Test public void cdShouldNotBeNull(){ assertNotNull(cd); } @Test public void play(){ assertEquals("Playing 哎呦不錯哦 by 周杰倫",player.play()); } }
一、自動化裝配測試
Spring從兩個角度來實現自動化裝配:this
組件掃描(ComponentScan):自動發現應用上下文中所建立的beanspa
自動裝配(Autowired):自動知足bean之間的依賴code
CompactDisc接口類和實現類:component
public interface CompactDisc { String play(); }
@Component public class SgtPeppers implements CompactDisc { private String title="哎呦不錯哦"; private String artist="周杰倫"; @Override public String play() { return "Playing "+title+" by "+artist; } }
MediaPalyer接口類和實現類xml
public interface MediaPlayer { String play(); } @Component public class CDPlayer implements MediaPlayer { private CompactDisc cd ; @Autowired public CDPlayer(CompactDisc cd){ this.cd=cd; } @Override public String play(){ return cd.play(); } }
配置類CDPlayerConfig:
@Configuration @ComponentScan public class CDPlayerConfig { }
@ComponentScan做用是掃描帶有@Component註解的類,併爲其建立bean。默認是掃描同一包下的類,固然也能夠加入參數,指定包名。
如@ComponentScan(basePackages={"com.zcs"})或者@ComponentScan(basePackageClasses={CDPlayer.class,DVDPlayer.class})(即這些類所在的包)
@Autowired知足自動依賴裝配,能夠做用在任何方法上面。
XML形式的自動裝配則修改測試類@ContextConfiguration,改爲加載spring-config.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://www.springframework.org/schema/context/spring-context.xsd"> <bean id="compactDisc" class="com.zcs.impl.SgtPeppers"></bean> <bean id="cdPlayer" class="com.zcs.impl.CDPlayer"> <constructor-arg ref="compactDisc"></constructor-arg> </bean> <context:component-scan base-package="com.zcs"> </beans>
二、顯示bean裝配
當想要將第三方庫中的組件裝配到你的應用中,在這種狀況下是沒有辦法在它的類上面添加@Component和@Autowired註解的,所以就不能使用自動化裝配的方案。
只能選擇java代碼或者xml顯示配置
首先能夠把兩個實現類上的@Component,還有配置類中的@ComponentScan,CDPlayer類中方法上的@Autowired註解去掉。
這個時候測試應該都通不過。
Java代碼方式:修改CDPlayerConfig配置類爲:
@Configuration public class CDPlayerConfig { @Bean public CompactDisc sgtPeppers(){ return new SgtPeppers(); } @Bean public MediaPlayer getCDPlayer(){ return new CDPlayer(sgtPeppers()); }
//@Bean
//public MediaPlayer getCDPlayer(CompactDisc compactDisc){ // return new CDPlayer(compactDisc); //}
}
再運行測試應該會經過了,解釋下 @Bean註解告訴Spring這個方法將會返回一個對象,該對象要註冊爲Spring應用上下文中的bean。方法體中包含了最終生成bean實列的邏輯。
第二個方法故意寫的奇怪一點,看起來CompactDisc是經過調用sgtPeppers()方法獲得的,但並不是如此,Spring會攔截對sgtPeppers方法的調用,轉而從上下文中直接獲取該方法所建立的bean,而不是每次都對其進行實際的調用。
好比:再添加一個方法(測試會通不過)
@Bean public MediaPlayer anotherCDPlayer() { return new CDPlayer(sgtPeppers()); }
這兩個方法依賴注入的CompactDisc將會是同一個bean。
固然經過狀況下用註釋的方法更容易理解一點。
XML方式:
首先CDPlayerTest爲XML方式,同時修改spring-config.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://www.springframework.org/schema/context/spring-context.xsd"> <bean id="compactDisc" class="com.zcs.impl.SgtPeppers"></bean> <bean id="cdPlayer" class="com.zcs.impl.CDPlayer"> <constructor-arg ref="compactDisc"></constructor-arg>
</bean> <context:component-scan base-package="com.zcs"/> </beans>
組件掃描方式的配置不去掉也是沒影響的。
補充:
複雜一點的構造方法
修改SgtPeppers的構造方法
public class SgtPeppers implements CompactDisc { private String title="哎呦不錯哦"; private String artist="周杰倫"; private List<String> tracks=new ArrayList<>(); public SgtPeppers(String title, String artist, List<String> tracks) { this.title = title; this.artist = artist; this.tracks = tracks; } @Override public String play() { return "Playing "+title+" by "+artist; } }
同時修改spring-config.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://www.springframework.org/schema/context/spring-context.xsd"> <bean id="compactDisc" class="com.zcs.impl.SgtPeppers"> <constructor-arg index="0" value="雪狼湖"/> <constructor-arg index="1" value="張學友"/> <constructor-arg index="2"> <list> <value>不老的傳說</value> <value>愛是永恆</value> </list> </constructor-arg> </bean> <bean id="cdPlayer" class="com.zcs.impl.CDPlayer"> <constructor-arg ref="compactDisc"></constructor-arg> </bean> <context:component-scan base-package="com.zcs"/> </beans>
還有屬性注入<property>,c和p命名空間使用就不細說了。對於xml的配置通常在java代碼中也會有對應的配置。但顯示配置用java代碼會類型安全一點
參考:spring實戰第4版