EasyPoi获取字段问题定位

一、 问题

项目中使用EasyPoi工具开发excel导出功能,导出类中有如下结构字段:
"X_XXX_XXX",字段首位只有一个字符。

使用导出api,发生异常:

There is no getter for property named 'XXX' in 'null'

检查实体类,存在对应的getXXX,setXXX方法。

这就很诡异了,为什么?

二、 分析

找到源码异常点在工具类PoiReflectorUtil中:

image.png

可以看到在method没有找到对应名称的字段:getMethods是一个Map用来保存字段信息,找到对应put方法:

image.png

我们从此工具类PoiReflectorUtil的初始化开始看:
在构造函数中分别通过反射获取了实例的get方法,set方法和属性:

image.png

addGetMethod(clazz)方法:

image.png

可以看到此方法做了三件事:

  1. 通过反射获取实体的所有方法
  2. 分别处理以“get”,"is"开头的方法
  3. 处理后的结果保存在map中

再看如何处理: 截取"get","set"或者"is" ,判断后面的字符:如果长度==1或者第一个字符不是大写则将首字符转换为小写。

image.png

好像发现了什么,结构为"X_XXX_XXX"的字段:"P_TEST_VLUE",根据JAVA的变量规则为:pTestValue,对应的get方法名“getPTestValue( )”,而根据上面的规则,因为"PTestValue"第二个字符为大写,所以并不会将首位转为小写!!!也许这就解释了为什么在后面的逻辑中找不到“pTestValue”字段。
在上一步的resolveGetterConflicts方法中通过addGetMethod加入getMethods保存。

image.png

addFileds(clazz)方法:

image.png

同样使用反射获取了所有的字段信息,并加入到了fieldList中。加入的字段为:“pTestValue”。
ps: 请注意这个方法:设置私有字段的访问权限

field.setAccessible(true)

最后再看抛出异常的地方:

由上面的分析可以发现问题所在,正由猜测的一样,因为在“getMethods”中保存的字段名为:“PTestValue”,而只有字段名为“pTestValue”,get方法取值为null:

Method method = getMethods.get(propertyName);

最终在执行导出方法的时候,执行到了前面抛出异常的方法:

image.png

四、总结

因为以前没有遇到过形如"X_XXX_XXX"的字段,对此通过反射获取实体类的方法不是很了解。只有查看源码才能发现端倪。
这里卖个关子,jackson序列化工具也有类似的问题。

你可能感兴趣的:(EasyPoi获取字段问题定位)