Spring xml 配置文件中的字符串值类型是如何通过 Spring的机制以正确的数据类型注入给目标属性的?
以下主要模拟将 String 转为 int 、date 类型。
首先 Spring 是结合了 java.beans.BeanInfo 实现了属性的转换。
1、模拟的demo类
package com.jd;
import java.beans.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.stream.Stream;
public class JavaBeanDemo {
public static void main(String[] args) {
try {
BeanInfo beanInfo = Introspector.getBeanInfo(Student.class, Object.class);
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
Stream.of(propertyDescriptors).forEach(System.out::println);
System.out.println();
Student student = new Student();
Stream.of(propertyDescriptors).forEach(propertyDescriptor -> {
String propertyName = propertyDescriptor.getName();
if ("id".equals(propertyName)) {
// 必须设置一下,否则会 NNP
propertyDescriptor.setPropertyEditorClass(IdPropertyEditor.class);
PropertyEditor propertyEditor = propertyDescriptor.createPropertyEditor(student);
Method setIdMethod = propertyDescriptor.getWriteMethod();
propertyEditor.addPropertyChangeListener(new SetPropertyChangeListener(student, setIdMethod));
propertyEditor.setAsText("99");
}
if ("birth".equals(propertyName)) {
// 必须设置一下,否则会 NNP
propertyDescriptor.setPropertyEditorClass(DatePropertyEditor.class);
PropertyEditor propertyEditor = propertyDescriptor.createPropertyEditor(student);
Method setBirthMethod = propertyDescriptor.getWriteMethod();
propertyEditor.addPropertyChangeListener(new SetPropertyChangeListener(student, setBirthMethod));
propertyEditor.setAsText("2017-09-01 22:00:00");
}
});
System.out.println(student);
} catch (Exception e) {
e.printStackTrace();
}
}
private static class SetPropertyChangeListener implements PropertyChangeListener {
private Object bean;
private Method setWriteMethod;
public SetPropertyChangeListener(Object bean, Method setWriteMethod) {
this.bean = bean;
this.setWriteMethod = setWriteMethod;
}
@Override
public void propertyChange(PropertyChangeEvent event) {
PropertyEditor source = (PropertyEditor) event.getSource();
try {
setWriteMethod.invoke(bean, source.getValue());
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
2、int 类型 PropertyEditor
package com.jd;
import org.springframework.util.StringUtils;
import java.beans.PropertyEditorSupport;
public class IdPropertyEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
if (StringUtils.hasText(text)) {
int id = Integer.valueOf(text);
setValue(id);
}
}
}
3、date 类型PropertyEditor
package com.jd;
import org.springframework.util.StringUtils;
import java.beans.PropertyEditorSupport;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DatePropertyEditor extends PropertyEditorSupport {
@Override
public void setAsText(String text) throws IllegalArgumentException {
if (StringUtils.hasText(text)) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat();
simpleDateFormat.applyPattern("yyyy-MM-dd HH:mm");
try {
Date date = simpleDateFormat.parse(text);
setValue(date);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
}
4、Java bean
package com.jd;
import java.util.Date;
public class Student {
private int id;
private String name;
private int age;
private Date birth;
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", birth=" + birth +
'}';
}
}