Java浅拷贝BeanUtils.copyProperties引发的RPC异常

文章讲述了作者在敏捷团队项目中遇到的ClassCastException问题,通过排查发现是由于BeanUtils.copyProperties的浅拷贝导致的。作者反思了原始方法的稳定性,并提出了使用MapStruct的建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

f43fc3e508a516d5a889e262356e095c.png

Tech

01 

背景

在今年的敏捷团队建设中,我通过Suite执行器实现了一键自动化单元测试。Juint除了Suite执行器还有哪些执行器呢?由此我的Runner探索之旅开始了!

近期参与了一个攻坚项目,前期因为其他流程原因,测试时间已经耽搁了好几天了,本以为已经解决了卡点,后续流程应该顺顺利利的,没想到 人在地铁上,bug从咚咚来~

没有任何修改的服务接口,抛出异常:

java.lang.ClassCastException: java.util.HashMap cannot be cast to cn.xxx.xxx.xxx.xxx.BatchInfo

02 

  

排查过程

  

理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目标页面展示到屏幕。

1、作为资深写bug的老司机,第一感觉是传参的报文格式有问题了,可以通过模拟报文排查。于是乎,在群里圈了服务提供方同学B看下,BG快速的用测试工具+本地debug的方式,验证了下报文格式,发现居然都调用成功了。。。

2、同步服务调用同学L,重点关注:1)、调用方的序列化方式;2)、最近代码改动逻辑是否有问题。L同学确认自己逻辑没有问题后,同步B同学和S同学,看内部是否有什么处理逻辑。。。

3、第二天早上一来,快速写了单测,确认服务端收到的报文格式,的确没有问题。于是乎,开始扒代码。。。发现可疑的代码:

BeanUtils.copyProperties(item,cargoInfo)

private List<CargoInfo> convertToCargoInfo(OutboundEventCallbackRequest outboundEventCallbackRequest) {
        return outboundEventCallbackRequest.getCargos().stream().map(item -> {
            CargoInfo cargoInfo = new CargoInfo();
            BeanUtils.copyProperties(item, cargoInfo);
            return cargoInfo;
    }).collect(Collectors.toList());
}

PS:客户端&服务端类关系

e58f44e9c6bd34ab56b5e763d0c8ed1b.png

因为BeanUtils.copyProperties属于浅拷贝,而浅拷贝只是调用子对象的set方法,并没有将所有属性拷贝(引用的一个内存地址)。所以将在进行调用时,JSF会因为反序列化时找不到对应的类,就会将其转换为Map。

直观图如下:

e243d8b3f50b8e0ba08447acb9631fa4.png

以上,初步定位原因,解决方式也就清晰了。

03 

  解决方案与后续反思 

 

理解,首先 MCube 会依据模板缓存状态判断是否需要网络获取最新模板,当获取到模板后进行模板加载,加载阶段会将产物转换为视图树的结构,转换完成后将通过表达式引擎解析表达式并取得正确的值,通过事件解析引擎解析用户自定义事件并完成事件的绑定,完成解析赋值以及事件绑定后进行视图的渲染,最终将目标页面展示到屏幕。    1.位图原理

去掉BeanUtils.copyProperties,进行手动赋值。最终解决了这个问题。

后续反思

1、想起王东岳老师的那句话,越原始的越稳定~

2、如果这种转换比较多,建议使用MapStruct

3、谨慎使用BeanUtils.copyProperties,请看:

a16db7e29830549d211bc382a88015b9.png

11af43d8bf0489ba42dfaa53c2b335cf.png

6ece7d063361296a74603b72804620c6.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值