Spring(三)裝配Bean:自動裝配Bean

  • 自動裝配(autowiring):有助於減小甚至消除配置<property>元素和<constructor-arg>元素,讓Spring自動識別如何裝配Bean的依賴關係。java

  • 自動檢測(autodiscovery):比自動裝配更進一步,讓Spring可以自動識別哪些類須要被配置成Spring Bean,從而減小對<bean>元素的使用。正則表達式


一、4種類型的自動裝配

  • byName——把與Bean的屬性具備相同名字(或者ID)的其餘Bean自動裝配到Bean的對應屬性中。若是沒有跟屬性的名字相匹配的Bean,則該屬性不進行裝配。spring

  • byType——把與Bean的屬性具備相同類型的其餘Bean自動裝配到Bean的對應屬性中。若是沒有跟屬性的名字相匹配的Bean,則該屬性不進行裝配。express

  • constructor——把與Bean的構造器入參具備相同類型的其餘Bean自動裝配到Bean構造器的對應入參中。ui

  • autodetect——首先嚐試使用constructor進行自動裝配。若是失敗,再嘗試使用byType進行自動裝配。spa


byName自動裝配code

——爲屬性自動裝配ID與該屬性同名的Beancomponent

例:xml

假設存在一個Instrumentalist類包含屬性song、instrument,如下是手動裝配Bean的方式。對象

<bean id="saxophone" class="com.roger.spring.beans.Saxophone" />

<bean id="kenny" class="com.roger.spring.beans.Instrumentalist">
    <property name="song" value="Jingle Bells" />
    <property name="instrument" ref="saxophone" />
</bean>

若是要利用byName自動裝配,就須要在使用<bean>元素定義Saxophone的時候,將Bean的id設置爲I和nstrumentalist屬性instrument同名的字面值。 經過配置autowire屬性就能夠利用此信息自動裝配 kenny 的 instrument 屬性了。

<bean id="instrument" class="com.roger.spring.beans.Saxophone" />

<bean id="kenny" class="com.roger.spring.beans.Instrumentalist"
    autowire="byName">
    <property name="song" value="Jingle Bells" />
</bean>


byType自動裝配

——Spring會尋找哪個Bean的類型與屬性的類型相同。

侷限:若是Spring尋找到多個Bean,它們的類型與須要自動裝配的屬性的類型都相匹配,這時候,Spring不會猜想哪個Bean更適合自動裝配,而是選擇拋出異常。因此,應用只容許存在一個Bean與須要自動裝配的屬性類型相匹配。

解決裝配歧義的問題:能夠爲自動裝配標識一個首選,或者取消某個Bean自動裝配的候選資格。

  • 標識首選

        利用<bean>的primary屬性, 默認爲true,所以要達到標識首選的目的,須要將其餘候選的primary屬性都設爲false。

  • 取消候選

        將<bean>的autowire-candidate屬性設爲false。


constructor自動裝配

——在Bean聲明中,不須要<constructor-arg>元素了

侷限:a. 具備和byType自動裝配相同的侷限,當發現多個Bean匹配某個構造器入參時,Spring不會猜想哪一個更適合;

          b. 若是一個類有多個構造器,它們都知足自動裝配的條件時,Spring也會猜想哪一個更適合。


默認自動裝配

    利用<beans>屬性default-autowire進行設置,默認爲none,表示都不使用自動裝配。能夠利用<bean>元素的autowire屬性來覆蓋<beans>的默認自動裝配策略。


二、使用註解裝配Bean

  • 使用註解方式容許更細粒度的自動裝配,能夠選擇性地標註某一個屬性來對其應用自動裝配。

  • Spring容器默認禁用註解裝配

    xml配置中啓用註解,利用context命名空間中<context:annotation-config>元素,以下所示:

<?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">
    
    <context:annotation-config />
    
</beans>


Spring支持集中不一樣的用於自動裝配的註解:

  • Spring自帶的@Autowired註解

  • JSR-330的@Inject註解

  • JSR-250的@Resource註解

@Autowired 默認是經過byType方式進行自動裝配的,經過結合@Qualifier註解能夠經過匹配Bean的id進行自動裝配。

如:

經過@Qualifier註解將範圍縮小,嘗試將id爲"guita"的bean注入。

@Autowired
@Qualifier("guita")
private Instrument instrument;

 a、@Resource默認是按照名稱來裝配注入的,只有當找不到與名稱匹配的bean纔會按照類型來裝配注入;

 b、@Autowired默認是按照類型裝配注入的,若是想按照名稱來轉配注入,則須要結合@Qualifier一塊兒使用;

 c、@Resource註解是由J2EE提供,而@Autowired是由Spring提供,故減小系統對spring的依賴建議使用  

       @Resource的方式;

d、@Resource和@Autowired均可以書寫標註在字段或者該字段的setter方法之上


三、自動檢測Bean

    即便<context:annotation-config>元素有助於徹底消除Spring配置中的<property>和<constructor-arg>元素,可是仍要使用<bean>元素顯示定義Bean。

    所以,藉助<context:component-scan>元素,除了完成與<context:annotation-config>同樣的工做,還容許Spring自動檢測Bean和定義Bean。中意味着不使用<bean>元素,Spring應用中的大多數(或全部)Bean都可以實現定義和裝配。

    還能夠經過<context:component-scan>元素的base-package屬性標識<context:component-scan>元素會掃描指定的包及其全部子包。

<?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">
    
    <context:component-scan
        base-package="com.roger.spring.beans">
    </context:component-scan>
    
</beans>

3.一、爲自動檢測標註Bean

    默認狀況下,<context:component-scan>查找使用構造型(stereotype)註解所標註的類。

這些特殊註解以下:

  • @Component——經過的構造型註解,標識該類爲Spring組件

  • @Controller——標識將該類定義爲Spring MVC controller

  • @Repository——標識將該類定義爲數據倉庫

  • @Service——標識將該類定義爲服務

  • 使用@Component標註的任意自定義註解


    Spring掃描發現@Component註解所標註的類,並自動地將它註冊爲Spring Bean,Bean的ID默認爲無限定類名(如:Person Bean的id爲person)。

    也可使用@Component("Roger")方式來指定Bean的id。

3.2過濾組件掃描

    經過爲<context:component-config>配置子元素<context:include-filter>或者<context:exclude-filter>來調整掃描行爲。

    <context:include-filter>的type和expression屬性一塊兒來定義組件掃描策略。

過濾器類型 描述
annotation
過濾器掃描使用指定註解所標註的那些類,經過expression屬性指定要掃描的註解
assignable 過濾器掃描派生於expression屬性所指定類型的那些類
aspectj 過濾器掃描與expression屬性所指定的AspectJ表達式所匹配的那些類
custom 使用自定義的org.springframework.core.type.TypeFilter實現類,該類由expression屬性指定
regex 過濾器掃描類的名稱與expression屬性所指定的正則表達式所匹配的那些類

例如:

<context:component-scan
    base-package="com.roger.spring.beans">
    <context:include-filter type="assignable"
        expression="com.roger.spring.Address" />
</context:component-scan>


四、使用Spring基於java的配置

4.一、建立基於Java的配置

用極少許的xml來啓用java配置:

<?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">
    
    <context:component-scan
        base-package="com.roger.spring.beans">
    </context:component-scan>
    
</beans>

    <context:component-scan>自動註冊那些使用某種構造型(stereotype)註解所標註的Bean。

    同時,也會自動加載使用@Configuration註解所標註的類。

4.二、定義一個配置類

  • 在基於java的配置裏使用@Configuration註解的java類,等價於xml配置中的<beans>元素。

  • @Configuration註解做爲一個標識告知Spring:這個類將包含一個或多個Spring Bean的定義。

  • 這些Bean的定義是使用@Bean註解所標註的方法。

例如:

有一個Person基類,Teacher類繼承Person類,如下,聲明一個簡單的id爲roger的Teacher Bean。

import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringConfig {
    //Bean declaration methods go here
    
    //聲明一個簡單的Bean
    @Bean
    public Person roger() {
        return new Teacher();
    }
}

    @Bean告知Spring這個方法將返回一個對象,該對象應該被註冊爲Spring應用上下文中的一個Bean,方法名做爲Bean的id。

4.三、使用Spring基於java的配置進行注入

例如:

注入一個引用

import org.springframework.context.annotation.Configuration;

@Configuration
public class SpringConfig {
    //Bean declaration methods go here
    
    @Bean
    public Address address() {
        return new Address();
    }
    
    @Bean
    public Person roger() {
        return new Teacher(address());
    }
}

注意:在Spring的java配置中,經過聲明方法引用一個Bean並不等同於調用該方法。經過@Bean註解標註address()方法,要在其餘Bean的聲明方法中引用這個方法時,Spring都會攔截方法的調用,並嘗試在應用上下文中查找該Bean,而不是讓方法建立一個新的實例。

相關文章
相關標籤/搜索