前期也写beanToMap、mapToBean的工具类,只是有点土而已。
今天的beanToMap、mapToBean比以往更具有健壮性、高效性,也算是了结了。
健壮性体现在:
若Bean中的实例成员变量为null,则在转换成Map后,对应的键值对中的值也为null。
若Map中没有与Bean的实例成员变量相对应键值对,则在转换成Bean后,Bean实例的那些成员变量也为null。
若Map中键值对的值的真实类型全是String,与Bean的实例成员变量类型无法挨个对应,则对Map中的Value挨个进行类型转换。
高效性体现在:
对于同一个Bean不会进行第二次内省和反射操作。在Bean第一次进行内省和反射操作后,将其操作结果存入缓存中。后面若再对Bean进行内省和反射操作时,先在缓存中看看该Bean是否出现过,若出现过,直接由缓存返回结果;若没有出现过,再对该Bean进行内省和反射操作,再将其操作结果存入缓存,最后返回操作结果。
一、核心代码介绍
private static List<Field> getBeanClassField(Class beanClass)
该方法通过传入的参数beanClass,运用内省和反射,将其所有的Field对象(继承的不要,没有对应的setter、getter方法的不要)取出,并存储于List<Field>集合中;再以beanClass的全限定类名为Key,以List<Field>为Value,存入Map<String, List<Field>>中。
这个Map<String, List<Field>>就是用作缓存的,对于同一个beanClass,只会进行一次内省和反射操作,第二次就从缓存中直接取出内省和反射的操作结果。
private static final Map<String, List<Field>> fieldListMap;
/*
该Map<String,List<Field>>用作缓存,避免对同一个beanClass进行重复的内省和反射操作
Key存储beanClass的全限定类名
Value存储关于beanClass的所有Field的集合List<Field>
*/
static {
fieldListMap = new TreeMap<>();
}
private static List<Field> getBeanClassField(Class beanClass) {
if (fieldListMap.containsKey(beanClass.getName()))
//若缓存Map<String, List<Field>>的Key中已存储beanClass的全限定类名
{
System.err.println("Leave it alone--------"+beanClass.getName()+"---------beanClassField from buffer-------");
return fieldListMap.get(beanClass.getName());
//则直接由缓存Map<String, List<Field>>返回List<Field>
//这样一来,就省去下面的一波内省、反射操作了
}
List<Field> fieldList = null;
Method writeMethod;
Method readMethod;
Field beanClassField;
String beanClassFieldName;
try {
BeanInfo beanInfo = Introspector.getBeanInfo(beanClass);//内省
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();//Field的描述器
fieldList = new ArrayList<>();
for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
readMethod = propertyDescriptor.getReadMethod();//与Field对应的读方法
writeMethod = propertyDescriptor.getWriteMethod();//与Field对应的写方法
if (readMethod != null && writeMethod != null) //读方法、写方法必须同时存在,这样判断是为了排除getClass()方法
{
beanClassF