天天看點

java淺拷貝BeanUtils.copyProperties引發的RPC異常

背景

近期參與了一個攻堅項目,前期因為其他流程原因,測試時間已經耽擱了好幾天了,本以為已經解決了卡點,後續流程應該順順利利的,沒想到 人在地鐵上,bug從咚咚來~

沒有任何修改的服務接口,抛出異常:

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

排查過程

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:用戶端&服務端類關系

java淺拷貝BeanUtils.copyProperties引發的RPC異常



因為BeanUtils.copyProperties屬于淺拷貝,而淺拷貝隻是調用子對象的set方法,并沒有将所有屬性拷貝(引用的一個記憶體位址)。是以将在進行調用時,JSF會因為反序列化時找不到對應的類,就會将其轉換為Map。

直覺圖如下:

java淺拷貝BeanUtils.copyProperties引發的RPC異常



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

解決方案

去掉BeanUtils.copyProperties,進行手動指派。最終解決了這個問題。

後續反思

1、想起王東嶽老師的那句話,越原始的越穩定~

2、如果這種轉換比較多,建議使用MapStruct

3、謹慎使用BeanUtils.copyProperties,請看:

java淺拷貝BeanUtils.copyProperties引發的RPC異常