当以一个字符串值来设置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。