spring配置的可選方案
Spring容器負責(zé)創(chuàng)建應(yīng)用程序中的bean并通過DI來協(xié)調(diào)這些對象之間的關(guān)系。作為開發(fā)人員需要告訴spring需要裝配哪些bean并且如何將其裝配到一起。spring提供了三種主要的裝配機制
- 在xml中進行顯示的裝配
- 在Java中進行配置
- 隱形的bean發(fā)現(xiàn)機制和自動配置
提供3種配置方案并不會使spring變得復(fù)雜。每種配置技術(shù)所提供的功能會出現(xiàn)一些重疊,所以在特定的場景中,確定哪種技術(shù)最為合適就會變得有些困難,但是不必緊張——在很多場景下,選擇那種方案很大程度上只是個人的喜好問題,你盡可能選擇自己喜歡的方式。并沒有唯一的答案,你所做出的選擇必須要適合你和你的項目。而且,我們也不是只能選擇一種配置方案,spring的配置風(fēng)格可以事互相搭配的,所以可以選擇使用xml裝配一些bean,使用spring基于Java的配置(JavaConfig)來裝配另外一些bean,而將剩下的bean讓spring去自動發(fā)現(xiàn)。
即便如此,我們建議是盡可能地使用自動配置機制。顯式配置越少越好。當(dāng)你必須要顯式配置bean的時候(比如,有些源代碼不是由你自己來維護的,而當(dāng)你需要為這些代碼配置bean的時候),我推薦使用類型安全并且比xml更佳強大的JavaConfig。最后,只有當(dāng)你要想使用便利的xml命名空間,并且在JavaConfig中沒有同樣的實現(xiàn)的時候,才應(yīng)該使用xml
自動化裝配bean
如果spring能夠進行自動化裝配的話,那又何苦還要顯示地將這些bean裝配到一起?
spring 從兩個角度來實現(xiàn)自動裝配
- 組件掃描(component scanning):spring會自動發(fā)現(xiàn)應(yīng)用上下文中所創(chuàng)建的bean
- 自動裝配(autowiring):spring自動滿足bean之間的依賴
組件掃描和自動裝配組合到一起就能發(fā)揮巨大的威力,它能夠?qū)@式配置降低到最少。
通過CD播放器的例子來說明自動化裝配
maven pom.xml 依賴
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.11.RELEASE</version>
</dependency>
<!--spring test包 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.11.RELEASE</version>
<scope>provided</scope>
</dependency>
</dependencies>
CompactDisc接口 【CD】
package soundsystem;
public interface CompactDisc {
void play();
}
CompactDisc實現(xiàn)類SgtPeppers
package soundsystem;
import org.springframework.stereotype.Component;
@Component
public class SgtPeppers implements CompactDisc {
private String title="遠走高飛";
private String artist="金志文"; //artist 中文為藝術(shù)家 畫家的意思
public void play() {
System.out.println("Playing "+title+" by "+artist);
}
}
**java配置類CDPlayerConfig **
package soundsystem;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan
public class CDPlayerConfig {
}
**測試類CDPlayerTest **
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);
}
}
劃重點
@Component這個簡單的注解表明該類會作為組件類,并告知spring要為這個類創(chuàng)建bean。
在程序中沒有必要顯式配置SgtPeppers bean,因為這個類使用了@Component注解,所以spring會為你把事情處理妥當(dāng)不過,組件掃描默認是不啟用的。我們還需要顯示配置一下spring,從而命令它去尋找?guī)в蠤Component注解的類,并為其創(chuàng)建bean類CDPlayerConfig通過java代碼定義了spring的裝配規(guī)則,類中并沒有顯式地聲明任何bean,只不過它使用了@ComponentScan注解,這個注解能夠在spring中啟用組件掃描,如果沒有其他配置的話,@ComponentScan默認會掃描與配置類相同的包,如果你更傾向于通過xml啟用組件掃描的話,可以使用Spring context命名空間的<context:component-scan>元素。在xml中的beans標(biāo)簽中添加
<context:component-scan base-package="soundsystem">CDPlayerTest使用了Spring的SpringJUnit4ClassRunner,以便在測試開始的時候自動創(chuàng)建Spring的應(yīng)用上下文。注解@ContextConfiguration會告訴它需要在CDPlayerConfig中加載配置。
為組件掃描的bean命名
Spring應(yīng)用上下文中所有的bean都會給定一個ID,在前面的例子當(dāng)中,盡管我們并沒有明確的給SgtPeppers bean設(shè)置ID,但Spring會根據(jù)類名為其指定一個ID。具體來講,這個bean所給定的ID為sgtPeppers,也就是將類名的第一個字母變?yōu)樾憽?/strong>
如果想為這個bean設(shè)置不同的ID,你所需要做的就是將期望的ID作為值傳遞給@Component注解。比如說,如果想將這個bean標(biāo)識為loneyHeartsClub,那么你需要將SgtPeppers類的@Component注解配置為如下所示:
@Component("loneyHeartsClub")
public class SgtPeppers implements CompactDisc{
...
}
還有另外一種為bean命名的方式,這種方式不使用@Component注解,而是使用java依賴注入規(guī)范(Java Dependency Injection)中所提供的@Named注解來為bean設(shè)置ID:
package soundsystem;
import javax.injection.Named;
@Named("loneyHeartsClub")
public class SgtPeppers implements CompactDisc{
...
}
Spring 支持將@Named作為@Component注解的替代方案。兩者之間有一些細微的差異,但是大多數(shù)場景中,他們是可以相互替代的。
不過我覺得就名字上而言,對于@Named并沒有像@Component那樣清楚的表明它是做什么的