欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用jvm sandbox對三層嵌套類型的改造示例

 更新時間:2023年08月11日 08:57:05   作者:李梨同學(xué)  
這篇文章主要為大家介紹了使用jvm sandbox對三層嵌套類型的改造示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

問題背景

先簡單介紹下基于jvm-sandbox的imock工具,是Java方法級別的mock,操作就是監(jiān)聽指定方法,返回指定的mock內(nèi)容。

jvm-sandbox 利用字節(jié)碼操作和自定義類加載器的技術(shù),將原始方法替換為模擬代碼,從而在應(yīng)用程序中實現(xiàn)方法級別的模擬。這種方法非常強大,但也需要對字節(jié)碼操作、類加載機制和 JVM 內(nèi)部原理有一定的理解。

公司要搭建一個方法級別的后端mock平臺,因此我在imock的基礎(chǔ)上進行二次開發(fā)進行使用。

問題描述

在mock某個三方接口的方法時遇到報錯:

ava.lang.ClassCastException: com.alibaba.fastjson.JSONObject cannot be cast to com.travelsky.angeldoe.output.PassengerFlightInfo

看樣子是本來應(yīng)該是JSONObject 無法轉(zhuǎn)化成PassengerFlightInfo類型,通過日志排查問題,定位到報錯代碼。

PassengerFlightInfo?passengerFlightInfo?=?JSON.parseObject(out
?.getPassengerFlightInfoList().get(0).toString(),?PassengerFlightInfo.class);

線上服務(wù)沒有報錯,測試mock環(huán)境報錯,那么顯然是數(shù)據(jù)的問題,通過Arthas追蹤方法返回的bean對比發(fā)現(xiàn),差異就是線上的PassengerFlightInfo是一個bean,測試的PassengerFlightInfo是一個object。差異由此出現(xiàn)。

那么問題的關(guān)鍵就在于,如何通過mock工具把object提前轉(zhuǎn)成bean。

解決方案

改造mock agent工具思路:通過我們的mock-module.jar實現(xiàn)。

  • 根據(jù)PsrInfoOutputBean初步解析returnObject,獲取list中的object
  • 將object解析成PassengerFlightInfo,再通過反射技術(shù)將bean反射回PsrInfoOutputBean

代碼實現(xiàn)

//針對cki特殊類型PsrInfoOutputBean
case?3:
????//獲取advice返回類型的類加載器
????ClassLoader?behaviorClassLoader?=?advice.getBehavior().getReturnType().getClassLoader();
????//加載最外層PsrInfoOutputBean
????Class<?>?targetClass?=?behaviorClassLoader.loadClass(ro.getClassNames()[0]);
????LogUtil.info2("targetClass=",?targetClass.toString());
????//根據(jù)目標類解析returnData
????Object?res1?=?JSON.parseObject(ro.getReturnData(),?targetClass);
????//賦值保存做對比
????Object?res0?=?res1;
????LogUtil.info2("res1-before=",?res1.toString());
????//?通過反射獲取passengerFlightInfoList
????List<Object>?passengerFlightInfoList?=?(List<Object>)?targetClass.getMethod("getPassengerFlightInfoList").invoke(res1);
????LogUtil.info2("passengerFlightInfoList=",?passengerFlightInfoList.toString());
????if?(!passengerFlightInfoList.isEmpty())?{
????????//?獲取?passengerFlightInfoList?列表中的第一個元素
????????Object?firstPassengerFlightInfoList?=?passengerFlightInfoList.get(0);
????????LogUtil.info2("firstPassengerFlightInfoList=",?firstPassengerFlightInfoList.toString());
????????//?將?firstFlightInfo?轉(zhuǎn)換成?JSON?字符串
????????String?firstFlightInfoJson?=?JSON.toJSONString(firstPassengerFlightInfoList);
????????//?獲取第三層額外目標?Bean?類的類名,使用同一類加載器
????????Class<?>?targetBeanClass?=?behaviorClassLoader.loadClass(ro.getClassNames()[2]);
????????LogUtil.info2("targetBeanClass=",?targetBeanClass.toString());
????????//根據(jù)類解析成bean
????????Object?targetBean?=?JSON.parseObject(firstFlightInfoJson,?targetBeanClass);
????????LogUtil.info2("targetBean=",?targetBean.toString());
????????//?創(chuàng)建一個新的passengerFlightInfoListNew?將?targetBean?添加到?passengerFlightInfoList?中
????????List<Object>?passengerFlightInfoListNew?=?new?ArrayList<>();
????????passengerFlightInfoListNew.add(targetBean);
????????//?設(shè)置?passengerFlightInfoList?屬性回?res1
????????try?{
????????????//?執(zhí)行反射方法,把passengerFlightInfoListNew反射回res
????????????Method?method?=?targetClass.getMethod("setPassengerFlightInfoList",?List.class);
????????????method.invoke(res1,?passengerFlightInfoListNew);
????????}?catch?(Exception?e)?{
????????????//?捕獲異常并打印日志
????????????LogUtil.info2("Error?occurred?while?invoking?method:=",?e.getMessage()+"|"+e);
????????}
????}
????LogUtil.info2("前后的兩個類equals嗎?=",?String.valueOf(res1.equals(res0)));
????LogUtil.info2("res1-after=",?res1.toString());
????ProcessController.returnImmediately(res1);
????break;

遇到的坑

外部獲取的類名不能直接通過Class.forName加載,如下代碼所示:

?//?使用目標?Bean?類名解析?JSON?字符串成目標?Bean
????????Class<?>?targetBeanClass?=?Class.forName(targetBeanClassName);

實際會報錯:"message": "com.taobao.rigel.rap.model.PsrInfoOutputBean cannot be cast to com.taobao.rigel.rap.model.PsrInfoOutputBean", 原因是這兩個bean雖然名字一樣,但是類加載器不同,就導(dǎo)致bean的實際是不一樣的。類是否相同可以用equals進行判斷。

因此正確的做法是,先獲取advice返回類型的類加載器,然后加載我們所需要的類,這樣業(yè)務(wù)的代碼就會認得我們的bean了。

???//獲取advice返回類型的類加載器
????ClassLoader?behaviorClassLoader?=?advice.getBehavior().getReturnType().getClassLoader();
????//加載最外層PsrInfoOutputBean
????Class<?>?targetClass?=?behaviorClassLoader.loadClass(ro.getClassNames()[0]);

題外話:

為啥出現(xiàn)了這個錯誤?

出現(xiàn)這個報錯和開發(fā)的強轉(zhuǎn)類型也有關(guān)系,本地做了個小測試,同樣的數(shù)據(jù)。(但咱也沒發(fā)改開發(fā)的代碼,只能提提建議。 = =)

1、當(dāng)前異常轉(zhuǎn)化:按照開發(fā)業(yè)務(wù)代碼中的list強轉(zhuǎn)對象

List<Object> list = JSON.*parseArray*(jsonString);
PassengerFlightInfo passengerFlightInfo = (PassengerFlightInfo) list.get(0);

這是使用強制類型轉(zhuǎn)換的方式,直接將 list 中的第一個元素強制轉(zhuǎn)換為 PassengerFlightInfo 對象。

這種方式在編譯時不會報錯,但如果 list 中的第一個元素不是 PassengerFlightInfo 對象,則會在運行時拋出 ClassCastException 異常。

2、正常轉(zhuǎn)化:優(yōu)化過后用toJavaObject方法

PassengerFlightInfo passengerFlightInfo = ((JSONObject)
list.get(0)).toJavaObject(PassengerFlightInfo.class);

這是使用 FastJSON 提供的 toJavaObject 方法,將 JSONObject 類型轉(zhuǎn)換為 PassengerFlightInfo 對象。

這種方式在運行時會檢查轉(zhuǎn)換是否可行,如果 JSONObject 不包含 PassengerFlightInfo 的屬性或結(jié)構(gòu)不匹配,會拋出異常。這種方式更安全,因為它提供了更多的轉(zhuǎn)換檢查。

推薦使用第二種方式,因為它更加健壯和安全,能夠更好地處理可能出現(xiàn)的異常情況,并提供更好的錯誤信息。

以上就是使用jvm sandbox對三層嵌套類型的改造示例的詳細內(nèi)容,更多關(guān)于jvm sandbox改造三層嵌套類型的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Mybatis-Plus中update()和updateById()將字段更新為null

    Mybatis-Plus中update()和updateById()將字段更新為null

    本文主要介紹了Mybatis-Plus中update()和updateById()將字段更新為null,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • drools的簡單入門案例場景分析

    drools的簡單入門案例場景分析

    drools是一款由JBoss組織提供的基于Java語言開發(fā)的開源規(guī)則引擎,可以將復(fù)雜且多變的業(yè)務(wù)規(guī)則從硬編碼中解放出來,這篇文章主要介紹了drools的簡單入門案例,需要的朋友可以參考下
    2022-05-05
  • 淺談MyBatis-plus入門使用

    淺談MyBatis-plus入門使用

    這幾天本人了解到了MyBatis-plus,一個 Mybatis 增強工具包.經(jīng)過一番研究,發(fā)現(xiàn)這玩意真的好用,不用寫任何 xml ,內(nèi)置通用的 Mapper,而且完全是面向?qū)ο缶幊?文檔給的示例代碼,跟之前用過的 sequelize (Node.js 的 ORM)非常像,因此本人也嘗試了一把, 需要的朋友可以參考下
    2021-05-05
  • Java中的StringTokenizer實現(xiàn)字符串切割詳解

    Java中的StringTokenizer實現(xiàn)字符串切割詳解

    這篇文章主要介紹了Java中的StringTokenizer實現(xiàn)字符串切割詳解,java.util工具包提供了字符串切割的工具類StringTokenizer,Spring等常見框架的字符串工具類(如Spring的StringUtils),需要的朋友可以參考下
    2024-01-01
  • Java中json使用方法_動力節(jié)點Java學(xué)院整理

    Java中json使用方法_動力節(jié)點Java學(xué)院整理

    JSON(JavaScript Object Notation) 是一種輕量級的數(shù)據(jù)交換格式, json是個非常重要的數(shù)據(jù)結(jié)構(gòu),在web開發(fā)中應(yīng)用十分廣泛。下面通過本文給大家講解Java中json使用方法,感興趣的朋友一起看看吧
    2017-07-07
  • Spring?Boot中@Validated注解不生效問題匯總大全

    Spring?Boot中@Validated注解不生效問題匯總大全

    這篇文章主要給大家介紹了關(guān)于Spring?Boot中@Validated注解不生效問題匯總的相關(guān)資料,@Validated注解是Spring框架中的一個注解,用于在方法參數(shù)上添加參數(shù)校驗規(guī)則,需要的朋友可以參考下
    2023-07-07
  • Spring Boot啟動流程斷點過程解析

    Spring Boot啟動流程斷點過程解析

    這篇文章主要介紹了Spring Boot啟動流程斷點過程解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • Java ArrayList與LinkedList及HashMap容器的用法區(qū)別

    Java ArrayList與LinkedList及HashMap容器的用法區(qū)別

    這篇文章主要介紹了Java ArrayList與LinkedList及HashMap容器的用法區(qū)別,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助
    2022-07-07
  • Spring Boot集成Spring Cloud Security進行安全增強的方法

    Spring Boot集成Spring Cloud Security進行安全增強的方法

    Spring Cloud Security是Spring Security的擴展,它提供了對Spring Cloud體系中的服務(wù)認證和授權(quán)的支持,包括OAuth2、JWT等,這篇文章主要介紹了Spring Boot集成Spring Cloud Security進行安全增強,需要的朋友可以參考下
    2024-11-11
  • logback使用MDCFilter日志過濾源碼解讀

    logback使用MDCFilter日志過濾源碼解讀

    這篇文章主要介紹了logback使用MDCFilter日志過濾源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-11-11

最新評論