《Spring實戰》第四版讀書筆記 第二章 裝配Bean

在Spring中,對象無需本身查找或建立與其所關聯的其餘對象。相反,容器負責把須要相互協做的對象引用賦予各個對象。java

建立應用對象之間協做關係的行爲一般稱爲裝配(wiring),這也是依賴注入的本質。spring

2.1 Spring配置的可選方案

Spring提供了三種主要的裝配機制:數組

  • 在XML中進行顯式配置;
  • 在Java中進行顯式配置;
  • 隱式的bean發現機制和自動裝配。

做者建議儘量的使用自動裝配的機制。顯式配置越少越好,當必需要顯式配置bean的時候(好比,有些源碼不是由你來維護的,而當你須要爲這些代碼配置bean的時候),推薦使用類型安全而且比XML更增強大的JavaConfig。最後,只有當你想要使用便利的XML命名空間,而且在JavaConfig中沒有一樣的實現是才應該使用XML。安全

2.2 自動化裝配bean

Spring從兩個角度實現自動化裝配:ide

  • 組件掃描(component scanning):Spring會自動發現應用上下文中所建立的bean;
  • 自動裝配(autowiring):Spring自動知足bean之間的依賴。

2.2.1 建立可被發現的bean

在類上使用@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中加載配置。

2.2.2 爲組件掃描的bean命名

在組件掃描中若是沒有明確的設置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。

2.2.3 設置組件掃描的基礎包

若是沒有爲@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 { }

2.2.4 經過爲bean添加註解實現自動裝配

能夠在構造器、setter方法、任何方法上使用@Autowired註解,Spring會嘗試知足方法參數上所聲明的依賴。假若有且只有一個bean匹配依賴需求,那麼這個bean將會被裝配進來。

若是沒有匹配的bean,那麼在應用上下文建立的時候會拋出異常。能夠將@Autowired的required屬性設置爲false,此時Spring會嘗試自動裝配,可是若是沒有匹配的bean的話該屬性將會爲null。

若是有多個bean都知足依賴關係,Spring將會拋出異常。

@Autowired是Spring特有的註解。可使用@Inject註解替代。

2.3 經過Java代碼裝配Bean

顯式的裝配方式有兩種:Java和XML。

2.3.1 建立配置類

@Configuration註解代表這個類是一個配置類,該類應該包含在Spring應用上下文中如何建立bean的細節。

2.3.2 聲明簡單bean

要在JavaConfig中聲明bean,須要編寫一個方法,這個方法會建立所需類型的實例,而後給這個方法添加@Bean註解。

@Bean註解會告訴Spring這個方法將返回一個對象,該對象要註冊爲Spring應用上下文中的bean。方法體中包含了最終產生bean實例的邏輯。

默認狀況下,bean的ID與方法名一致。若是想爲其設置一個不一樣的名字,能夠重命名該方法,也能夠經過@Bean的name屬性指定。

2.3.3 藉助JavaConfig實現注入

在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之中。

2.4 經過XML裝配Bean

2.4.1 建立XML配置規範

在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>

2.4.2 聲明一個簡單的<bean>

<bean>元素相似於JavaConfig中的@Bean註解。

若是沒有給定ID,因此這個bean將會根據全限定類名來進行命名。例如「soundsystem.SgtPeppers#0「,其中「#0」是一個計數形式,用來區分相同類型的其餘bean。

2.4.3 藉助構造器注入初始化bean

構造器注入有兩種基本的配置方案可供選擇:

  • <constructon-arg>元素;
  • 使用Spring 3.0 所引入的c-命名空間。

構造器注入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甚至是數組。

2.4.4 設置屬性

<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,其中包含值或引用

2.5 導入和混合配置

2.5.1 在JavaConfig中引用XML配置

使用@Import註解引用其餘JavaConfig配置,使用@ImportResource註解引入XML配置。

@Configuration
@Import(CDPlayerConfig.class)
@ImportResource("classpath:cd-config.xml")
public class SoundSystemConfig {
    
}

2.5.2 在XML配置中引用JavaConfig

在XML中可使用<import>元素來引用其餘XML配置。

將JavaConfig做爲bean使用<bean>元素導入XML配置文件。

相關文章
相關標籤/搜索