参考资料
- 聊聊Spring中的数据绑定 — BeanWrapper以及Java内省Introspector和PropertyDescriptor【享学Spring】
- 聊聊Spring中的数据绑定 — 属性访问器PropertyAccessor和实现类DirectFieldAccessor的使用【享学Spring】
目录
一. 前置知识
内省(Introspector)
是Java 语言对 JavaBean 类属性、事件的一种缺省处理方法,是操作JavaBean的一套API。
什么是JavaBean?
JavaBean是一种规范,大家都按照约定好的一套规则写的Java类。
- 类是public的,然后有个无参的构造函数
- 属性是private的,通过设置set属性名()和get属性名()来访问
二. 前期准备
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
@Getter
@Setter
@NoArgsConstructor
public class Student {
private String personId;
private String humanName;
private String age;
}
import lombok.Data;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
@Data
public class Person {
private String id;
private String email;
private BigDecimal money;
// 因为要通过BeanWrapper的setPropertyValue方法赋值,因此此处要有初始值
private List<String> hobbyList = new ArrayList<>();
// 因为要通过BeanWrapper的setPropertyValue方法赋值,因此此处要有初始值
private Student student = new Student();
}
三. getPropertyDescriptor(‘属性名’)
- 获取
PropertyDescriptor
对象
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.PropertyAccessorFactory;
import java.beans.PropertyDescriptor;
// 创建person对象
Person person = new Person();
// 通过Spring的PropertyAccessorFactory对象创建BeanWrapper对象
BeanWrapper personBeanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(person);
// 获取id属性的PropertyDescriptor对象,如果id属性不存在或者没有get/set方法会报错
PropertyDescriptor idDescriptor = personBeanWrapper.getPropertyDescriptor("id");
System.out.println(idDescriptor);
四. getPropertyType()
- 获取属性类型
// 获取id属性的类型
Class<?> propertyType = idDescriptor.getPropertyType();
System.out.println(String.class.equals(propertyType)); // true
五. getPropertyDescriptors()
- 获取所有的属性名
import java.beans.FeatureDescriptor;
import java.util.stream.Collectors;
// 获取出JavaBean中所有的Field属性名
List<String> filedNameList = Arrays.stream(personBeanWrapper.getPropertyDescriptors())
.map(FeatureDescriptor::getName)
.filter(name -> !"class".equals(name))
.collect(Collectors.toList());
for (String fieldName : filedNameList) {
System.out.println(fieldName);
}
// email hobbyList id money student
六. 获取并执行set和get方法
getWriteMethod()
: 获取set方法getReadMethod
: 获取get方法
import java.lang.reflect.Method;
import java.beans.PropertyDescriptor;
// 获取email属性名
PropertyDescriptor emailProperty = personBeanWrapper.getPropertyDescriptor("email");
// 获取email的set方法对象并设置value
Method emailSetMethod = emailProperty.getWriteMethod();
emailSetMethod.invoke(person, "1355930128@qq.com");
// 获取email的get方法对象并获取value
Method emailGetMethod = emailProperty.getReadMethod();
Object result = emailGetMethod.invoke(person);
System.out.println(result); // 1355930128@qq.com
七. 设置集合或对象属性
// 设置集合属性
List<String> hobbyList = Arrays.asList("吃饭", "睡觉", "打豆豆");
for (int i = 0; i < hobbyList.size(); i++) {
personBeanWrapper.setPropertyValue("hobbyList[" + i + "]", hobbyList.get(i));
}
// 设置对象属性,对象需要提供无参构造方法并被初始化
Map<String, String> studentPropertyMap = new HashMap<>(){
{
put("personId", "110120119");
put("humanName", "贾飞天");
put("age", "18");
}
};
studentPropertyMap.forEach((propertyName, value) ->
personBeanWrapper.setPropertyValue("student." + propertyName, value)
);
System.out.println(person);