本文為原創,如需轉載,請注明作者和出處,謝謝!
裝配Bean是Spring的一個非常重要的功能。我們可以通過Spring在XML文件中配置Java Bean,然后通過ApplicationContext來獲得Bean的對象實例。在配置Bean時,需要對構造方法的參數,屬性進行初始化。對于Java簡單類型或簡單類型的List、Map等數據類型初始化非常簡單,如下面就是一個對簡單類型屬性和構造方法參數進行初始化的配置代碼:
<!-- 要求Spring2.0或Spring2.5 scope="prototype"相當于Spring1.x的singleton="false" -->
<bean id="my" class="bean.MyClass" scope="prototype">
<constructor-arg>
<value>my value1</value>
</constructor-arg>
<property name="name">
<value>皮球</value>
</property>
<property name="myList">
<list>
<value>value1</value>
<value>value2</value>
</list>
</property>
</bean>
但對于復雜類型的屬性或參數,如一個屬性的類型是另外一個Java Class,這樣就必須在配置文件中再聲明這個Java Class,如果這種情況很多時,或是我們做的類要release時,就會給開發人員增加很多工作量。讓我們先來舉個例子。假設有兩個類:Contact和PhoneNumber,Contact的phoneNumber屬性的類型是PhoneNumber,代碼如下:
Contact類
package bean;
public class Contact
{
private PhoneNumber phoneNumber;
public PhoneNumber getPhoneNumber()
{
return phoneNumber;
}
public void setPhoneNumber(PhoneNumber phoneNumber)
{
this.phoneNumber = phoneNumber;
}
}
PhoneNumber類
package bean;
public class PhoneNumber
{
private String number;
public PhoneNumber(String s)
{
this.number = s;
}
public String getNumber()
{
return number;
}
}
如果直接在XML配置文件中裝配Contact類,就需要先裝配PhoneNumber類,代碼如下:
<?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:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<bean id="contact" class="bean.Contact">
<property name="phoneNumber">
<ref bean="phoneNumber"/>
</property>
</bean>
<bean id="phoneNumber" class="bean.PhoneNumber">
<constructor-arg>
<value>12345678</value>
</constructor-arg>
</bean>
</beans>
從上面的代碼中可以看到,裝載Contact的同時,也裝載了PhoneNumber。但如果使用了屬性編輯器,就可以無需裝載PhoneNumber就可以裝載Contact了。
編寫自己的屬性編輯器的步驟很簡單,屬性編輯器類需要從java.beans.PropertyEditorSupport類繼承,在這個類中有一個setAsText方法,這個方法有一個String類型的參數,通過這個方法,可以將String類型的參數值轉換成其他類型的屬性。在這個方法中我們還需要使用一個setValue方法,就來指定轉換后的對象實例。好,現在我們來實現這個簡單的編輯器類,代碼如下:
package editor;
public class PhoneEditor extends java.beans.PropertyEditorSupport
{
@Override
public void setAsText(String text) throws IllegalArgumentException
{
setValue(new bean.PhoneNumber(text));
}
}
這個類的代碼非常簡單,在setAsText方法中只有一行代碼,實際上只是建立一個PhoneNumber對象實例,并將text屬性值作為參數值傳入PhoneNumber的構造方法。接下來我們在配置文件中安裝這個屬性編輯器(實際上是裝配org.springframework.beans.factory.config.CustomEditorConfigurer類),代碼如下:
<bean id="customerEditor"
class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="bean.PhoneNumber">
<bean id="phoneEditor" class="editor.PhoneEditor"/>
</entry>
</map>
</property>
</bean>
從上面的代碼可以看出,屬性編輯器是使用了CustomEditorConfigurer的customEditors屬性進行安裝的。這是一個Map類型的屬性。key的值必須是屬性編輯器最終轉換后的類型名,如在本例中,要將文本的參數值轉換成bean.PhoneNumber類型的值,因此,key必須為bean.PhoneNumber。 下面我們來使用PhoneEditor屬性編輯器類來裝配Contact類,代碼如下:
<bean id="contact" class="bean.Contact">
<property name="phoneNumber">
<value>87654321</value>
</property>
</bean>
也許大家都注意到了上面這段代碼的變化,在設置phoneNumber屬性默認值時,不再使用<ref>標簽來引用phoneNumber對象,而是直接使用了<value>來設置一個文本的電話號。Spring當遇到這種情況時,也就是說,某個屬性值和屬性類型不一致時(如本例中一個是文本,一個是PhoneNumber類型),會先找一下屬性類型是否有相應的屬性編輯器已經被安裝,在本例中將以bean.PhoneNumber作為key來查找,正好找到上面安裝的PhoneEditor,因此,Spring就會調用PhoneEditor類中的setAsValue方法來設置PhoneNumber對象實例,然后Spring在內部又分調用getValue來獲得PhoneNumber對象實例,并將其賦給Contact的phoneNumber屬性。其實所有類型的bean.PhoneNumber的屬性都可以使用這個屬性編輯器。
大家可以看看,這樣做是不是簡單的多!尤其是在發布通用的framework或程序時,就更為簡單了。在Spring中已經定義了很多這種屬性編輯器,如我們可以使用org.springframework.beans.propertyeditors.URLEditor將字符串映射成java.net.URL對象。下面的代碼通過ApplicationContext來獲得Contact的對象實例,并輸出其phoneNumber屬性值:
import org.springframework.context.*;
import org.springframework.context.support.*;
public class Test
{
public static void main(String[] args)
{
// 上面的配置代碼都在applicationContext.xml文件中
ApplicationContext context = new FileSystemXmlApplicationContext("src\\applicationContext.xml");
bean.Contact contact = (bean.Contact) context.getBean("contact");
System.out.println(contact.getPhoneNumber().getNumber());
}
}
注:實際上,屬性編輯器本身是由Java提供了,Spring只是利用了這一特性使裝配一個Bean更容易而已。
新浪微博:http://t.sina.com.cn/androidguy 昵稱:李寧_Lining