當以一個字符串值來設置bean屬性時,Spring IoC 容器最終使用標準的JavaBean PropertyEditor來將這些字符串轉化成複雜的數據類型。Spring預先註冊了一些PropertyEditor(舉例來說,將一個以字符串表示的Class轉化成Class對象)。除此之外,Java標準的JavaBean PropertyEditor會識別在同一包結構下的類和它對應的命名恰當的Editor,並自動將其作爲這個類的的Editor。
比如
Address類有一個PhoneNumber屬性
package com.springinaction.propertyeditor;
public class Address {
private PhoneNumber phoneNumber;
public PhoneNumber getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(PhoneNumber phoneNumber) {
this.phoneNumber = phoneNumber;
}
}
PhoneNumber類:
package com.springinaction.propertyeditor;
public class PhoneNumber {
private String areaCode;
private String prefix;
private String number;
public PhoneNumber(String areaCode, String prefix, String number) {
this.areaCode = areaCode;
this.prefix = prefix;
this.number = number;
}
//省略getter和setter,toString()方法
}
PhoneNumberEditor類:
package com.springinaction.propertyeditor;
import java.beans.PropertyEditorSupport;
public class PhoneNumberEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
// TODO Auto-generated method stub
// super.setAsText(text);
String stripped = strippedNonNumber(text);
String areaCode = stripped.substring(0,3);
String prefix = stripped.substring(3,6);
String number = stripped.substring(6);
PhoneNumber phone = new PhoneNumber(areaCode,prefix,number);
setValue(phone);
}
public String strippedNonNumber(String original){
StringBuffer allNumbers = new StringBuffer();
for(int i=0;i<original.length();i++){
char c = original.charAt(i);
if(Character.isDigit(c)){
allNumbers.append(c);
}
}
return allNumbers.toString();
}
}
配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<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-2.0.xsd">
<bean id="address" class="com.springinaction.propertyeditor.Address">
<property name="phoneNumber">
<value>800-900-6789</value>
</property>
</bean>
</beans>
測試代碼:
package com.springinaction.propertyeditor;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
public class PropertyEditorTest {
public static void main(String[] args) {
BeanFactory bf = new XmlBeanFactory(new ClassPathResource(
"com/springinaction/propertyeditor/editor.xml"));
Address address = (Address) bf.getBean("address");
System.out.println(address.getPhoneNumber());
}
}
因爲PhoneNumber類和PhoneNumberEditor類在同一個包下,不用註冊PhoneNumberEditor,就能將字符串類型的800-900-6789轉換成PhoneNumber類型。
如果PhoneNumber類相應的編輯器類名不是PhoneNumberEditor,而是別的名字,比如PhoneEditor,上面其它的代碼和配置都不變,再運行測試類的時候就會報
java.lang.IllegalArgumentException: Cannot convert value of type [java.lang.String] to required type [com.springinaction.propertyeditor.PhoneNumber]異常。
要解決這個問題,需要註冊自定義的編輯器和將XmlBeanFactory改成ApplicationContext。
可以通過customEditors屬性註冊編輯器或者通過propertyEditorRegistrars屬性註冊編輯器。
customEditors屬性方式註冊:
<?xml version="1.0" encoding="UTF-8"?>
<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-2.0.xsd">
<bean id="customEditorConfigurer"
class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="com.springinaction.propertyeditor.PhoneNumber">
<bean id="phoneEditor" class="com.springinaction.propertyeditor.PhoneEditor">
</bean>
</entry>
</map>
</property>
</bean>
<bean id="address" class="com.springinaction.propertyeditor.Address">
<property name="phoneNumber">
<value>800-900-6789</value>
</property>
</bean>
</beans>
propertyEditorRegistrars屬性方式註冊:
<?xml version="1.0" encoding="UTF-8"?>
<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-2.0.xsd">
<bean id="editorRegister" class="com.springinaction.propertyeditor.PhoneEditorRegister" />
<bean id="customEditorConfigurer"
class="org.springframework.beans.factory.config.CustomEditorConfigurer">
<property name="propertyEditorRegistrars">
<ref bean="editorRegister" />
</property>
</bean>
<bean id="address" class="com.springinaction.propertyeditor.Address">
<property name="phoneNumber">
<value>800-900-6789</value>
</property>
</bean>
</beans>
添加的PhoneEditorRegister類代碼如下,它實現了PropertyEditorRegistrar,註冊了PhoneEditor。
package com.springinaction.propertyeditor;
import org.springframework.beans.PropertyEditorRegistrar;
import org.springframework.beans.PropertyEditorRegistry;
public class PhoneEditorRegister implements PropertyEditorRegistrar {
public void registerCustomEditors(PropertyEditorRegistry registry) {
registry.registerCustomEditor(com.springinaction.propertyeditor.PhoneNumber.class,
new PhoneEditor());
}
}
測試類修改如下:
package com.springinaction.propertyeditor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class PropertyEditorTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext(
"com/springinaction/propertyeditor/editor.xml");
Address address = (Address) context.getBean("address");
System.out.println(address.getPhoneNumber());
}
}
這時在運行測試類,字符串類型的值800-900-6789就可以成功轉換成PhoneNumber類型了,控制檯會輸出800-900-6789。