前言
最近做项目,需要写一个序列化相关的框架,在javabean的属性的反射过程中,居然出现不兼容的现象。
1. 旧版本属性反射
Javabean由于书写不标准,出现属性与get、set方法不对应,模拟bean注意setNameR与getNameR方法。
public class TestBean {
private String name;
private Integer age;
public String getNameR() {
return name;
}
public void setNameR(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
但是非常奇怪,序列化属性什么都正常,经过源码分析,原来是通过
Introspector.getBeanInfo(TestBean.class)
这种方式反射get与set方法。
public class ReflectMain {
public static void main(String[] args) throws IntrospectionException {
BeanInfo beanInfo = Introspector.getBeanInfo(TestBean.class);
Field[] fields = TestBean.class.getDeclaredFields();
for (PropertyDescriptor descriptor : beanInfo.getPropertyDescriptors()){
if ("class".equals(descriptor.getName())){
continue;
}
System.out.println("writeMethod:\t" + descriptor.getWriteMethod().getName() + "\t-----\t" + "readMethod:\t" + descriptor.getReadMethod().getName());
}
System.out.println("----------------------------");
}
}
结果如下:
writeMethod: setAge ----- readMethod: getAge
writeMethod: setNameR ----- readMethod: getNameR
----------------------------
2. 标准的反射
由于写的新框架使用java标准的set与get方法
public class ReflectMain {
public static void main(String[] args) throws IntrospectionException {
Field[] fields = TestBean.class.getDeclaredFields();
for (Field field : fields){
System.out.println("field is:\t" + field.getName());
}
System.out.println("----------------------------");
}
}
使用属性名称,判断是否boolean值,拼接set或者is方法(这是ali不推荐boolean使用is开头命名的原因,序列化方式可能会导致is丢失)
结果如下:
field is: name
field is: age
----------------------------
3.原理分析
反射获取set和get方法的方式不一样,标准的javabean是属性与set、get方法名称一致
使用fastjson测试
public class FastJsonTest {
public static void main(String[] args) {
TestBean testBean = new TestBean();
testBean.setAge(11);
testBean.setNameR("Tom");
String json = JSON.toJSONString(testBean);
System.out.println(json);
}
}
结果如下:
{"age":11,"nameR":"Tom"}
属性,变成nameR了。
总结
javabean的标准非常重要,属性与set、get方法对应对于框架的开发非常重要。
如果生产上出现这个问题,解决方法:
由于序列化后的json是nameR,那么可以将javabean的属性改为nameR,这样就实现了标准的javabean,序列化正常