Spring筆記---最小化Spring配置

Spring提供了幾種技巧,可以幫助減少XML配置數量:
>.自動裝配(autowiring):有助於減少甚至消除配置<property>元素和<constructor-arg>元素,讓Spring自動識別如何裝配Bean的依賴關係。
>.自動檢測(autodiscovery):比自動裝配更進一步,讓Spring自動識別哪些類需要被配置成Spring Bean,從而減少對<bean>元素的使用。

1.自動裝配:應對明確的裝配場景
涉及自動裝配Bean的依賴關係時,Spring提供瞭如下4中自動裝配策略:
>.byName---把與Bean的屬性具有相同名字(或ID)的其他Bean自動裝配到Bean的對應屬性中。如果沒有和屬性名字相匹配的Bean,則該屬性不裝配;

>.byType---把與Bean的屬性具有相同類型的其他Bean自動裝配到Bean的對應屬性中。若沒有,則該屬性不裝配;

>.constructor---把與Bean的構造器入參具有相同類型的其他Bean自動裝配到Bean構造器對應的入參中;

>.autodetect---首先嚐試使用constructor自動裝配。若失敗,再嘗試使用byType自動裝配。

(1).byName
eg.
<bean id="kenny" class="spring.domain.Instrumentalist">
 <property name="song" value="Jingle Bells" />
 <property name="instrument" ref="piano" />
</bean>

這裏,我們使用property屬性顯示配置了Kenny的instrument屬性。
但是,如果我們使用<bean>定義Piano時,把Bean的id屬性設置爲instrument:
<bean id="piano" class="spring.domain.Piano">
在上面的例子中,Piano Bean的id屬性與kenny Bean的instrument屬性的名字是一樣的,Spring可以利用此信息自動裝配kenny的instrument屬性:
<bean id="kenny" class="spring.domain.Instrumentalist" autowire="byName">
 <property name="song" value="Jingle Bells" />
</bean>

byName自動裝配遵循一項約定:爲屬性自動裝配ID與該屬性名字相同的Bean。通過設置autowire屬性爲byName,Spring將特殊對待kenny的所有屬性,爲這些屬性尋找與其名字相同的Spring Bean。


(2).byType自動裝配:
類似於byName自動裝配,只不過不再匹配屬性的名字而是檢查屬性的類型。當使用byType自動裝配時,Spring會尋找與屬性類型相匹配的Bean。

存在的問題是:當有多個Bean的類型與匹配的屬性類型相同,Spring會拋異常。可以給對應的Bean配primary屬性來增加優先級。實際上默認的都是true,還需要將其他的設置爲false。在自動裝配時,如果希望排除一些Bean,可以設置排除的Bean的autowire-candidate屬性爲false。

(3).constructor自動裝配;

(4).autodetect自動裝配:當配置一個Bean的autowire屬性爲autodetect時,Spring將首先嚐試使用constructor自動裝配,如果沒有發現與構造器匹配的Bean時,Spring將嘗試使用byType自動裝配。

(5).默認自動裝配:在<beans>元素裏配置autowire屬性,這個配置將對所有bean生效,但是也可以通過配置具體的<bean>元素的autowire屬性來覆蓋<beans>元素所配置的默認自動裝配策略。

另外,還可以混合使用自動裝配和顯示裝配,以解決有些自動裝配(byType)可能產生的裝配不確定性問題,顯示裝配將覆蓋自動裝配。

2.使用註解自動裝配:
sprng2.5開始,Spring開始支持註解自動裝配。
Spring容器默認禁用註解裝配。因此,使用前要在Spring配置中啓用它。最簡單的啓用方式是使用Spring的context命名空間配置中的<context:annotation-config>元素。
Spring支持幾種不同的用於自動裝配的註解:
>.Spring自帶的@Autowired註解;
>.JSR-330的@Inject註解;
>.JSR-250的@Resource註解。

1).autowired自動裝配:
如果使用@Autowired讓spring自動裝配演奏家(Instrumentalist)Bean的instrument屬性。則可以通過以下方法標註實現:
>.標註setInstrument()方法
@Autowired
public void setInstrument(Instrument instrument)
{
    this.instrument = instrument;
}
這樣,就可移除定義Instrumentalist的instrument屬性所對應的<property>元素了。當Spring發現對setInstrument()方法使用了@Autowired註解時,Spring會嘗試對該方法執行byType自動裝配。
>.標註需要自動裝配Bean應用的任意方法:
@Autowired註解不僅能用來標註setter方法,還可以標註需要自動裝配Bean應用的任意方法,
@Autowired
public void anyMethod(Instrument instrument)
{
    this.instrument = instrument;
}
甚至是構造器:
@Autowired
public Instrumentalist(Instrument instrument)
{
    this.instrument = instrument;
}
當對構造器進行標註時,@Autowired註解表示當創建Bean時,即使在Spring的XML配置文件中沒有使用<constructor-arg>元素配置Bean,該構造器也需要自動裝配。
>.直接標註屬性,包括private屬性,並刪除setter方法:
@Autowired
private Instrument instrument;

@Autowired註解的限制:應用中只能有一個Bean適合裝配到@Autowired註解所標註的屬性或參數中。如果沒有匹配的Bean,或者存在多個匹配的Bean,@Autowired註解就會遇到一些麻煩。
默認情況下,@Autowired具有強契約特徵,其所標註的屬性或參數必須是可裝配的。如果沒有Bean可以裝配到@Autowired所標註的屬性或參數中,自動裝配就會失敗,拋出NoSuchBeanDefinitionException異常。
對於上面的兩個限制:
第一個,沒有匹配的,通過設置@Autowired的required屬性爲false來配置自動裝配是可選的
@Autowired(required=false)
private Instrument instrument;
這裏,Spring將嘗試匹配instrument屬性,但是如果沒有找到與之匹配類型的Instrument的Bean,應用不會發生任何問題,而instrument屬性的值會設置爲null。
required屬性可以用於@Autowired註解使用的任何地方。但當使用構造器裝配時,只有一個構造器可以將@Autowired的required屬性設置爲true。其他構造只能將required屬性設置爲false。另外,當使用@Autowired標註多個構造器時,Spring會從滿足裝配條件的構造器中選擇入參最多的那個構造器。
第二個,有多個Bean滿足裝配條件,並且都可以被裝配到屬性或參數中,這是爲了避免歧義,可以配合使用Spring的@Qualifier註解:
@Autowired
@Qualifier("guitar")
private Instrument instrument;
如上所示,@Qualifier註解將嘗試注入ID的guitar的Bean。除了使用Bean的ID來縮小選擇範圍,還可以通過在Bean上直接使用qualifier來縮小範圍。
<bean class="...spring.domain.Guitar">
 <qualifier value="stringed">
</bean>
還可以使用@Qualifier註解來直接標註Guitar類。
除此之外,我們可以創建自定義限定器(Qualifier)。
Spring的@Autowired註解時減少Spring XML配置的一種方法,但使用它的類會引入對Spring的特定依賴。

2).藉助@Inject實現基於標準的自動裝配
爲了統一各種依賴注入框架的編程模型,JCP發佈了Java依賴注入規範JSR-330,即@Inject。
和@Autowired一樣,@Autowired可以自動裝配屬性、方法和構造器,但是@Inject沒有required屬性,所以@Inject註解所標註的依賴關係必須存在,否則拋異常。
除了@Inject註解,JSR-330還提供了一種技巧。與其直接注入一個引用,可以要求@Inject注入一個Provider。Provider接口可以實現Bean引用的延遲注入以及注入Bean的多個實例等功能。
相對於@Autowired的使用@Qualifier,@Inject使用@Named註解來限定歧義的Bean定義。@Named使用方法和@Qualifier類似。另外,JSR-330也包含@Qualifier註解,但是不建議使用,而是鼓勵使用該註解來創建自定義的限定器註解,和@Qualifier創建自定義註解一樣。
在註解中還可以使用表達式:
@Value("...")
private Stirng song;
自動裝配是一種強大的技術,讓Spring自動識別出如何將Bean裝配在一起,從而幫助我們減少應用中的XML配置。

3.自動檢測Bean
爲了配置Spring自動檢測,需使用<context:component-scan>代替<context:annotation-config>元素。<context:component-scan>除了完成與<context:annotation-config>一樣的工作,還允許Spring自動檢測Bean和定義Bean。
<context:component-scan base-package="com.spring.domain">
</context:component-scan>
通過上面的配置,<context:component-scan>元素會掃描指定的包及其所有子包,並查找出能自動註冊爲Spring Bean的類。base-package屬性標識了<context:component-scan>元素所掃描的包。
默認情況下,<context:component-scan>查找使用構造型(stereotype)註解所標註的類,這些註解包括:
>.@Component---通用的構造型註解,標識該類爲Spring組件;
>.@Controller---標識將該類定義爲Spring MVC controller;
>.@Repository---標識將該類定義爲數據倉庫;
>.@Service---標識將該類定義爲服務;
>.使用@Component標註的任意自定義註解。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章