大家好,又见面了,我是你们的朋友全栈君。
想要实现 Map 转为 Bean 的功能,使用了org.apache.commons.beanutils.BeanUtils.populate(object, map); 期间遇到了一些问题,遂整理了一下。
先抛结论,是因为 lombok 的配置问题。
问题发现及测试验证
maven依赖
代码语言:javascript复制<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>
测试代码如下
代码语言:javascript复制//bean使用了lombok自动生成 getter/setter
@lombok.Data
@lombok.experimental.Accessors (chain = true)
public class JavaBean {
private String id;
private String name;
}
// 测试方法
@Test
public void _map2Bean() throws Exception {
Map map = new HashMap();
map.put("id", "aa");
JavaBean bean = new JavaBean();
org.apache.commons.beanutils.BeanUtils.populate(bean, map);
System.out.println(bean.getId());
}
测试结果发现,bean的id为null,没有实现预想中的,将map的id值设置到 bean 的id属性上去。
讲道理,不应该。 遂debug了一波测试用例,发现BeanUtils底层使用了PropertyDescriptor反射获取属性,通过PropertyDescriptor的getWriteMethod()方法获取属性的setter方法,最后通过setter方法给属性赋值。 在调试时发现是 getWriteMethod()方法返回了 null(也就是获取不到setter方法),导致后续没有执行赋值操作。
为什么呢?明明我们使用了 lombok 自动给 JavaBean 生成了 getter/setter,难道 lombok 还有猫腻?
通过反编译插件,查看了JavaBean编译后的class文件,咋一看没什么,但发现!!!
自动生成的 setter 方法签名不是返回 void,而是返回了 本身。
检查了下,发现JavaBean类使用了 lombok的Accessors 注解,该注解用于支持链式调用,即 new JavaBean().setId("xxx").setName("xxx");
这种写法。
为确定是否@lombok.experimental.Accessors (chain = true)注解影响,去掉 JavaBean的注解,重新测试了一下,发现正常了
代码语言:javascript复制@lombok.Data
//@lombok.experimental.Accessors (chain = true)//用于支持链式调用,去掉该注解进行测试
public class JavaBean {
private String id;
private String name;
}
// 测试方法
@Test
public void _map2Bean() throws Exception {
Map map = new HashMap();
map.put("id", "aa");
JavaBean bean = new JavaBean();
org.apache.commons.beanutils.BeanUtils.populate(bean, map);
System.out.println(bean.getId());
}
好了,原因知道了。 Accessors 注解导致JavaBean生成的 setter 方法不被 PropertyDescriptor 识别,才导致获取 setter为null。
解决办法:
1、去掉 Accessors 注解 2、摸索中… 发现了这个 Introspector.findMethod(Class<?> cls, String methodName, int argCount, Class args[]); 能按方法名获取Method对象,那么要自己实现转换逻辑,可以尝试,摸索中…
end
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/189153.html原文链接:https://javaforall.cn