1. 程式人生 > 其它 >跟著柴毛毛學Spring(3)——簡化Bean的配置

跟著柴毛毛學Spring(3)——簡化Bean的配置

通過前面的學習,我們會感覺到對於一個有較多Bean的大專案,Spring的配置會比較複雜。那麼接下來我們就介紹如何簡化Spring的配置。

簡化Spring的配置主要分為兩類: 1. 自動裝配 2. 自動掃描

下面就詳細介紹這兩種簡化配置的方式。

自動裝配

自動裝配的種類

  1. byName:根據屬性的名字自動裝配
  2. byType:根據屬性的型別自動裝配
  3. constructor:根據構造器的引數型別自動裝配
  4. autodetect:最佳自動裝配。首先採用constructor自動裝配,若沒有發現與構造器相匹配的Bean時,採用byType進行自動裝配。

使用XML實現自動裝配

  1. byName:根據屬性的名字裝配 在bean標籤中新增屬性autowire=”byName”。當Spring啟動時,會尋找與person中成員變數名字相同的bean,並將該bean注給person的成員變數。
    <bean id="person" class="com.njupt.Person" autowire="byName">
    </bean>
  1. byType:根據屬性的型別裝配 在bean標籤中新增屬性autowire=”byName”。當Spring啟動時,會尋找與person中成員變數型別相同的bean,並將該bean注給person的成員變數。
    <bean id="person" class="com.njupt.Person" autowire="byType">
    </bean>

byType的缺點:如果某一型別的bean有多個,那Spring在通過byType為屬性尋找同類型的bean時就會丟擲異常。 解決方案: - 為相同型別的bean設定是否首選 在需要被首選的bean中作如下設定:

<bean id="person" class="com.njupt.Person" primary="true">
    </bean>

在不需要被首選的bean中作如下設定:

<bean id="person" class="com.njupt.Person" primary="false">
    </bean>
  • 取消某一些相同型別bean的候選資格 使用auto-candidate屬性取消某些bean的候選資格,Spring在為屬性尋找同類型的bean時直接排除這些bean。
<bean id="person" class="com.njupt.Person" default-candidate="false">
    </bean>
  1. constructor:根據構造器的引數的型別裝配 autowire設定為constructor後,Spring會尋找與建構函式的引數型別相同的bean,並注入給這個建構函式。
<bean id="person" class="com.njupt.Person" autowire="constructor">
    </bean>

構造器的自動裝配本質上仍是通過byType進行裝配,只不過autowire=”constructor”時,Spring會對構造器的引數進行自動裝配,而autowire=”byType”時,Spring會對bean的成員變數進行自動裝配。

構造器的自動裝配和byType自動裝配具有相同的缺點:當某一型別的bean有多個時,Spring無法確定究竟選擇哪個bean,就直接丟擲異常。 此外,構造器的自動裝配還有個獨特的缺點:當構造器有多個時,Spring也無法選擇究竟初始化哪個構造器,因此也直接跑出異常。

  1. autodetect:最佳自動裝配。Spring要初始化一個設定了autowire=”autodetect”的bean時,首先採用構造器裝配,若沒有發現與構造器相匹配的Bean或構造器有多個時,就採用byType對屬性進行裝配。

使用預設自動裝配 上述自動裝配的方法都是針對單個bean,如果要讓beans下的所有bean均使用某種自動裝配策略,那麼在beans標籤中增加如下配置:

default-autowire="byType"
  • 注意1:在beans中設定了default-autowire後,這個引數僅對當前beans標籤之間的bean有效。
  • 注意2:採用預設自動裝配後,仍然可以在bean中設定特有的自動裝配策略,bean中的自動裝配策略會覆蓋預設策略。
  • 注意3:使用了自動裝配後,我們仍然可以在bean中通過constructor-arg屬性和property屬性對bean進行顯示裝配。 這種混合使用顯示裝配和自動裝配的方式能夠成功地解決byType出現的不確定性問題
  • 注意4:如果使用了constructor來實現構造器引數的自動裝配,那麼就不能混合使用autowire=”constructor”屬性和constructor-arg標籤。

使用註解實現自動裝配

使用註解裝配其實就是把原本XML中bean中的autowire=”xxx”屬性搬到了Bean類的Java程式碼中了。功能上沒啥差別。 下面就來介紹如何使用註解實現自動裝配。

1. 開啟註解自動裝配

在beans中作如下配置:

<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans    
    http://www.springframework.org/schema/beans/spring-beans-4.5.xsd">

    <context:annotation-config>

</beans>

2. 使用@Autowired標註需要自動裝配的函式或屬性

當Bean中的屬性、函式被標記@Autowired後,Spring在建立這個bean的物件時,會通過byType尋找與屬性、函式引數相同型別的bean進行自動裝配。 - 用@Autowired標註建構函式

    @Autowired
    public Person(String name,long id){
        this.name = name;
        this.id = id;
    }
  • 用@Autowired標註普通函式
    @Autowired
    public void createInstance(){
        System.out.println("物件被建立啦!");
    }
  • 用@Autowired標註屬性
    @Autowired
    private Father father;

@Autowired本質上採用byType進行自動裝配,因此也存在與byType一樣的問題:若同一型別的bean有多個時,或找不到該型別的bean,Spring就會丟擲異常。

@Autowired弊端的應對策略

  1. 若同一型別的bean有多個 若採用xml設定bean的自動裝配,則可以使用顯示裝配的方式,手動設定需要注入的引數,而使用註解自動裝配時,可以使用@Qualifier縮小候選bean的範圍,具體操作如下:
    @Autowired
    @Qualifier("father")
    private Father father;

@Qualifier(“ID”)會根據bean的id為father裝配。

  1. 若找不到某一型別的bean 如果bean中的某些屬性、引數不需要初始化值也能接受的話,那就為該屬性或引數的@Autowired新增required屬性:
    @Autowired(required="false")
    public Person(String name,long id){
        this.name = name;
        this.id = id;
    }

此時,如果Spring找不到與建構函式的引數相同型別的bean的話,就賦上null。 注意:若一個bean有多個建構函式時,只有一個建構函式可以設為@Autowired(required=true),其餘的建構函式都只能設為@Autowired(required=false)

在註解中使用SpEL表示式

通過前面學習我們知道,在Spring的XML配置中,可以使用SpEL表示式來實現手動裝配。同樣,在註解中也可以使用SpEL表示式實現手動裝配。 - 將名為father的bean注入給建構函式:

    @Value("#{father}")
    public Person(Father father){
        this.father = father;
    }
  • 將father物件中的id注入給id:
    @Value("#{father.id}")
    public void setId(long id){
        this.id = id;
    }

自動檢測

自動裝配能夠減少bean標籤下property標籤和constructor-arg標籤的數量,而自動檢測能降低bean標籤的數量。

1. 開啟Spring的自動檢測

腰開啟自動檢測功能,需要在XML的beans標籤中作如下配置: - base-package: 表示要掃描的包

<beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans    
    http://www.springframework.org/schema/beans/spring-beans-4.5.xsd">

    <context:component-scan base-package="com.xxx"></context:component-scan>

</beans>

2. 為需要自動減的bean新增@Component註解

要讓一個Java類變成一個Bean,需要在類上加上@Component註解。Spring在啟動的時候會到base-package指定的包下尋找被@Component標記的類,把他們初始化為bean,儲存在SpringContext中。 - 將型別的小寫作為bean的名字:

@Component
class Person{
}
  • 指定bean的名字:
@Component("person")
class Person{
}

3. 過濾被掃描的bean

使用Java代替XML配置

雖然使用註解已經大大減少Spring中的XML配置,但仍然需要少量的XML配置,我們可以將XML配置用Java程式碼實現,從而完全避免了XML配置。

1. 定義一個Spring配置類

用@Configuration標籤標註一個類,表示這個類是Spring的配置類:

@Comfiguration
class Person{
    ……
}

2. 宣告一個bean

在Spring的配置類中,使用@Bean標籤標註一個bean。 - 函式名:bean的id - 返回值:bean的型別 - 函式體:初始化這個bean

@Comfiguration
class Person{
    @Bean
    public Person person(){
        //構造器注入
        Person person = new Person("柴毛毛");
        //屬性注入
        person.setAge(22);
        return person;
    }
}

3. 使用Java進行注入

在採用Java進行Spring的配置中,對bean屬性和構造器的注入非常簡單,只需在函式中操作即可:

@Comfiguration
class Person{
    @Bean
    public Person person(){
        return new Person();
    }
}

採用Java代替XML配置的好處

在XML配置中,bean的型別是用String表示的,因此只有在執行結點才能發現bean的型別是否寫錯;而在Java配置中,在編譯階段就能發現bean的型別是否出錯,從而能夠儘早地發現錯誤。