為什麼不推薦使用 BeanUtils copyProperties 複製資料?

Mondo 科技 更新 2024-01-30

在實際業務開發中,我們經常會遇到 VO、BO、PO、DTO 等物件屬性之間的賦值,當屬性較多時,我們使用 get、set 來賦值比較大量的工作,所以很多人會選擇使用 Spring 提供的複製工具 Beanutils 的 copyproperties 方法,完成物件間屬性的複製。 這樣一來,我們可以大大減少手動編寫物件屬性賦值所需的工作量,那麼既然這麼方便,為什麼不建議使用呢?下面我們來看看 beanutilscopyproperties 資料複製一些常見的

這個坑可以細分為以下兩種型別:

1)同一屬性的型別不同。

在實際開發中,很有可能同乙個欄位的型別被定義在不同的類中,比如id,A類中定義的型別可能是long,B類中定義的型別是string,在這種情況下,如果beanutilscopy屬性,複製會失敗,導致對應的字段為 null,對應的情況如下:

public class beanutilstest }@data@allargsconstructorclass sourcepojo@dataclass targetpojo
對應的結果如下:

可以看到,由於型別不一致,複製的 id 字段值為 null。

2)同一字段分別使用包型別和基本型別。

如果對欄位分別使用包裝類和基型別,則在未傳遞實際值時將發生異常,如以下示例所示:

public class beanutilstest }@dataclass sourcepojo@dataclass targetpojo
在測試用例中,id 字段分別使用複製源和複製目標中的包裝型別和基型別,您可以看到在下面的複製過程中發生了異常。

注意:如果 Boolean 屬性使用基型別和包裝型別,並且屬性名稱以 is 開頭,例如 issuccess,則複製將失敗。

在業務開發中,我們可能需要複製一些字段,如果複製的資料中的某些欄位有空值,但是需要複製的相同字段對應的值不是空,如果直接使用 beanutilsCopyProperties,則複製資料的 null 值將覆蓋複製資料的字段,導致原始資料失效。

對應案例如下:

public class beanutilstest }@dataclass sourcepojo@dataclass targetpojo
對應的結果如下:

您可以看到,最初在複製目標結果中具有值的使用者名字段被 null 覆蓋。 雖然你可以使用 beanutilsCopyProperties,帶有自定義的 convertutilsbean 來複製一些字段,但這也比較複雜,它失去了 beanutils 的使用。copyproperties 對複製資料很有意義,因此不建議這樣做。

使用 beanutils 時當使用 copyproperties 複製資料時,如果專案中同時引入了 Spring 的 bean 包和 Apache 的 beanutils 包,如果包匯入錯誤,很可能導致資料複製失敗,排查時不容易找到。 我們通常在 sping 包中使用 copy 方法,兩者的區別如下:

源物件在左邊,目標物件在右邊)public static void copyproperties(object source, object target) 丟擲 beansexception 源物件在右邊,目標物件在左邊)public static void copyproperties(object dest, object orig) throws illegalaccessexception, invocationtargetexception
在開發或故障排除過程中,如果我們在鏈結中查詢字段值 (來電者沒有通過它我們可以使用全文搜尋來查詢其對應的賦值方法(如設定模式、構建模式等),但是如果在鏈結中使用了beanutils.copy屬性,則難以快速定位賦值位置,導致故障排除效率低下。

內部類資料無法正常複製,即使型別和欄位名稱相同也無法複製成功,如下圖所示

公共類 beanutilstest }以下是類資訊,直接顯示在乙個piece@data@tostringpublic類 sourcepojo} 中@data@tostringpublic類 targetpojo}
其工作原理如下:

在上面的例子中,複製源和複製目標中有乙個內部類 innerclass,雖然內部類屬性相同,類名相同,但是在不同的類中,所以 Spring 會認為屬性不同,所以資料不會被複製。

在這裡,我將首先回顧一下深拷貝和精簡拷貝。

淺拷貝指建立乙個新物件,該物件與原始物件具有相同的屬性值,但仍共享引用型別的屬性的相同引用。 也就是說,在淺拷貝中,當原始內容的引用屬性值發生變化時,複製物件的引用屬性值也會發生變化。

深拷貝指建立具有與原始物件相同的屬性值的新物件,包括引用型別的屬性。 深層複製以遞迴方式複製引用的物件,從而建立乙個全新的物件,因此深層複製複製的物件與原始物件完全分開。

下面是它可能看起來像的示例:

public class beanutilstest }@data@allargsconstructorclass card @noargsconstructor@allargsconstructor@dataclass person
其工作原理如下:

總結:通過執行結果可以發現,複製後一旦修改了原物件的引用型別資料,就會導致複製資料的值異常,這也是難以排查的。

beanutils.copyproperties底層是通過反射獲取物件的set和get方法,然後通過get和set完成資料的複製,在整體複製中效率較低。

使用方法如下beanutils.copyproperties為了更容易直觀地看到效果,這裡以複製 10,000 次為例

public class beanutilstest system.out.println("複製方法:"+(system.currenttimemillis()-copystarttime));long setstarttime = system.currenttimemillis();for(int i = 0; i < 10000; i++)system.out.println("set 方法:"+(system.currenttimemillis()-setstarttime));data@allargsconstructor@noargsconstructorclass user
以下是執行效率結果的比較:

可以發現,常規集和 beanutilsCopyProperties,效能差距非常大。 因此,請使用 beanutilscopyproperties。

這就是使用 beanutils 的全部內容這些陷阱大多比較隱蔽,排查問題並不容易,所以不建議使用 beanutilscopy屬性。 歡迎對文章中的不足之處進行補充和糾正。

作者:京東科技 孫揚偉.

*:京東雲開發者社群 **請註明**。

相關問題答案

    為什麼不建議選擇朝西南的房子?

    在某些情況下,朝向西南的房屋可能會出現一些問題,但並非普遍不適合所有情況。以下是一些可能的原因,但請注意,這不是絕對的。.照明問題 在某些地區,朝西南的房屋在夏季可能會暴露在強烈的陽光下,導致室內溫度公升高。這會影響生活舒適度,尤其是在炎熱的季節。然而,在冬季,朝西南的房屋可以享受更長的日照時間,這...

    為什麼不建議吃黑麥?黑麥有什麼缺點嗎?

    黑麥是一種非常健康的食物,富含多種營養物質,包括膳食纖維 B 族維生素和礦物質。然而,對於某些人來說,黑麥可能會有問題。首先,黑麥中含有麥麩,這是一種不易消化的纖維,如果過量食用,可能會引起胃腸道不適,如腹瀉 腹痛等症狀。其次,黑麥還含有一種叫做穀胱甘肽的物質,可能會干擾人體對銅的吸收和利用,從而導...

    為什麼女孩不做眉毛紋身?帶你了解背後的真相,慶幸自己沒有跟風

    為什麼女孩不做眉毛紋身?帶你了解背後的真相,慶幸自己沒有跟風 隨著科技的變革,一些美容工作逐漸融入我們的生活,無論是男生還是女生都特別漂亮,都想給人展示完美的外表。在聽人說話的時候,我們都會看著對方的臉,進行交談,這是對人最基本的尊重,眉毛和眼睛在臉上也很重要,可以改變乙個人的容貌。所以出門前,我們...

    為什麼不建議老人和兒童進行近視手術?

    家長們總是擔心孩子的近視越來越嚴重,中老年人經常被視力模糊所困擾,這些人能做近視手術嗎?為什麼在去醫院檢查時,醫護人員一直在強調 太老或太年輕的人都不適合近視手術!一般來說,近視手術的合適年齡是至歲。為什麼近視手術不適合其他年齡段?答案是確保手術的有效性!首先,我們需要明確一點 近視手術只能 矯正 ...

    為什麼不建議選擇朝西南的房子?這四點是硬傷!

    買房需要考慮的因素很多,其中房子的方向是比較重要的考慮因素,雖然西南朝向的房子有一些優點,但也有缺點,導致有些人不推薦選擇西南朝南的房子,有四大重傷是我們不能接受的!不推薦朝西南的房子有幾個原因 西日照 朝西南的房子夏季陽光明媚,尤其是下午,會暴露在強烈的西陽光下,導致室內溫度公升高,居住者會感到悶...