1. 程式人生 > 實用技巧 >自動裝配 Bean

自動裝配 Bean

所謂自動裝配,就是將一個 Bean 注入到其他 Bean 的 Property 中,類似於以下:

<bean id = "customer" class = "com.shiyanlou.spring.autowire.common.Customer" autowire = "byName" />

Spring 支援 5 種自動裝配模式,如下:

  • no —— 預設情況下,不自動裝配,通過 ref attribute 手動設定。
  • byName —— 根據 Property 的 Name 自動裝配,如果一個 bean 的 name,和另一個 bean 中的 Property 的 name 相同,則自動裝配這個 bean 到 Property 中。
  • byType —— 根據 Property 的資料型別( Type )自動裝配,如果一個 bean 的資料型別,相容另一個 bean 中 Property 的資料型別,則自動裝配。
  • constructor —— 根據建構函式引數的資料型別,進行 byType 模式的自動裝配。
  • autodetect —— 如果發現預設的建構函式,用 constructor 模式,否則,用 byType 模式。

下例中演示自動裝配,CustomerService.java 如下:

package com.shiyanlou.spring.services;

import com.shiyanlou.spring.dao.CustomerDAO;

public class CustomerService {
    CustomerDAO customerDAO;

    public void setCustomerDAO(CustomerDAO customerDAO) {
        this.customerDAO = customerDAO;
    }

    @Override
    public String toString() {
        return "CustomerService [customerDAO=" + customerDAO + "]";
    }

}

CustomerDAO.java 如下:

package com.shiyanlou.spring.dao;

public class CustomerDAO {
    @Override
    public String toString(){
        return "Hello , This is CustomerDAO";
    }
}

Auto-Wiring no

預設情況下,需要通過 ref 來裝配 bean ,如下:

 <bean id = "customerService" class = "com.shiyanlou.spring.services.CustomerService">
  <property name = "customerDAO" ref = "customerDAO" />
  </bean>
 <bean id = "customerDAO" class = "com.shiyanlou.spring.dao.CustomerDAO" />

Auto-Wiring byName

根據屬性 Property 的名字裝配 bean,這種情況,CustomerService 設定了 autowire = "byName",Spring 會自動尋找與屬性名字 customerDAO 相同的 bean,找到後,通過呼叫 setCustomerDAO(CustomerDAO customerDAO) 將其注入屬性。

 <bean id = "customerService" class = "com.shiyanlou.spring.services.CustomerService" autowire = "byName">
 </bean>
 <bean id = "customerDAO" class = "com.shiyanlou.spring.dao.CustomerDAO" />

如果根據 Property name 找不到對應的 bean 配置,如下:

 <bean id = "customerService" class = "com.shiyanlou.spring.services.CustomerService" autowire = "byName">
 </bean>
 <bean id = "customerDAO_another" class = "com.shiyanlou.spring.dao.CustomerDAO" />

CustomerService 中 Property 名字是 customerDAO,但是配置檔案中找不到 customerDAO,只有 customerDAO_another,這時就會裝配失敗。執行後,CustomerService 中 customerDAO = null。

Auto-Wiring byType

根據屬性 Property 的資料型別自動裝配,這種情況,CustomerService 設定了 autowire = "byType",Spring 會自動尋找與屬性型別相同的 bean,找到後,通過呼叫 setCustomerDAO(CustomerDAO customerDAO) 將其注入。

 <bean id = "customerService" class = "com.shiyanlou.spring.services.CustomerService" autowire = "byType">
 </bean>
 <bean id = "customerDAO" class = "com.shiyanlou.spring.dao.CustomerDAO" />

如果配置檔案中有兩個型別相同的 bean 會怎樣呢?如下:

 <bean id = "customerService" class = "com.shiyanlou.spring.services.CustomerService" autowire = "byType">
 </bean>
 <bean id = "customerDAO" class = "com.shiyanlou.spring.dao.CustomerDAO" />
<bean id = "customerDAO_another" class = "com.shiyanlou.spring.dao.CustomerDAO" />

一旦配置如上,有兩種相同資料型別的 bean 被配置,將丟擲 UnsatisfiedDependencyException 異常,見以下:Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException。所以,一旦選擇了 byType 型別的自動裝配,請確認你的配置檔案中每個資料型別定義一個唯一的 bean。

Auto-Wiring constructor

這種情況下,Spring 會尋找與引數資料型別相同的 bean,通過建構函式 public Customer(Person person) 將其注入。

 <bean id = "customerService" class = "com.shiyanlou.spring.services.CustomerService" autowire = "constructor">
 </bean>
 <bean id = "customerDAO" class = "com.shiyanlou.spring.dao.CustomerDAO" />

注意:專案中 autowire 結合 dependency-check 一起使用是一種很好的方法,這樣能夠確保屬性總是可以成功注入。如下:

 <bean id = "customerService" class = "com.shiyanlou.spring.services.CustomerService" autowire = "autodetect" dependency-check = "objects">
 </bean>
 <bean id = "customerDAO" class = "com.shiyanlou.spring.dao.CustomerDAO" />