PropertyDescriptor获取getWriteMethod为null,使用了lombok

想要实现 Map 转为 Bean 的功能,使用了org.apache.commons.beanutils.BeanUtils.populate(object, map);
期间遇到了一些问题,遂整理了一下。

先抛结论,是因为 lombok 的配置问题。

问题发现及测试验证

maven依赖

<dependency>
	<groupId>commons-beanutils</groupId>
	<artifactId>commons-beanutils</artifactId>
	<version>1.9.4</version>
</dependency>

测试代码如下

//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的注解,重新测试了一下,发现正常了

@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

  • 7
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
HibernateValidatorJSR303的参考实现使用指南.pdf JSR 303 的参考实现 使用指南 由 Hardy Ferentschik和Gunnar Morling and thanks to Shaozhuang Liu 4.3.1.Final 版权 © 2009 - 2011 Red Hat, Inc. & Gunnar Morling June 20, 2011 序言 1. 开始入门 1.1. 第一个Maven项目 1.2. 添加约束 1.3. 校验约束 1.4. 更进一步 2. Validation step by step 2.1. 定义约束 2.1.1. 字段级(field level) 约束 2.1.2. 属性级别约束 2.1.3. 类级别约束 2.1.4. 约束继承 2.1.5. 对象图 2.2. 校验约束 2.2.1. 获取一个Validator的实例 2.2.2. Validator中的方法 2.2.3. ConstraintViolation 中的方法 2.2.4. 验证失败提示信息解析 2.3. 校验组 2.3.1. 校验组序列 2.3.2. 对一个类重定义其默认校验组 2.4. 内置的约束条件 2.4.1. Bean Validation constraints 2.4.2. Additional constraints 3. 创建自己的约束规则 3.1. 创建一个简单的约束条件 3.1.1. 约束标注 3.1.2. 约束校验器 3.1.3. 校验错误信息 3.1.4. 应用约束条件 3.2. 约束条件组合 4. XML configuration 4.1. validation.xml 4.2. 映射约束 5. Bootstrapping 5.1. Configuration 和 ValidatorFactory 5.2. ValidationProviderResolver 5.3. MessageInterpolator 5.3.1. ResourceBundleLocator 5.4. TraversableResolver 5.5. ConstraintValidatorFactory 6. Metadata API 6.1. BeanDescriptor 6.2. PropertyDescriptor 6.3. ElementDescriptor 6.4. ConstraintDescriptor 7. 与其他框架集成 7.1. OSGi 7.2. 与数据库集成校验 7.3. ORM集成 7.3.1. 基于Hibernate事件模型的校验 7.3.2. JPA 7.4. 展示层校验 8. Hibernate Validator Specifics 8.1. Public API 8.2. Fail fast mode 8.3. Method validation 8.3.1. Defining method-level constraints 8.3.2. Evaluating method-level constraints 8.3.3. Retrieving method-level constraint meta data 8.4. Programmatic constraint definition 8.5. Boolean composition for constraint composition 9. Annotation Processor 9.1. 前提条件 9.2. 特性 9.3. 配置项 9.4. 使用标注处理器 9.4.1. 命令行编译 9.4.2. IDE集成 9.5. 已知问题 10. 进一步阅读

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值