使用BeanUtils.copyProperties進(jìn)行對(duì)象之間的屬性賦值

問題引入

需要將不同的兩個(gè)對(duì)象實(shí)例進(jìn)行屬性復(fù)制,從而基于源對(duì)象的屬性信息進(jìn)行后續(xù)操作,而不改變?cè)磳?duì)象的屬性信息,比如DTO數(shù)據(jù)傳輸對(duì)象和數(shù)據(jù)對(duì)象DO,我們需要將DO對(duì)象進(jìn)行屬性復(fù)制到DTO,但是對(duì)象格式又不一樣,所以我們需要編寫映射代碼將對(duì)象中的屬性值從一種類型轉(zhuǎn)換成另一種類型。

這種轉(zhuǎn)換最原始的方式就是手動(dòng)編寫大量的 get/set代碼,當(dāng)然這是我們開發(fā)過程不愿意去做的,因?yàn)樗_實(shí)顯得很繁瑣。為了解決這一痛點(diǎn),就誕生了一些方便的類庫(kù),常用的有 apache的 BeanUtils,spring的 BeanUtils,這些庫(kù)可以幫助我們輕松的實(shí)現(xiàn)對(duì)象屬性的拷貝而不需要我們?cè)偈謩?dòng)get/set.

在介紹之前,我們先來看下關(guān)于對(duì)象拷貝的前置知識(shí),淺拷貝和深拷貝。

前置知識(shí)

如果在拷貝這個(gè)對(duì)象的時(shí)候,只對(duì)基本數(shù)據(jù)類型進(jìn)行了拷貝,而對(duì)引用數(shù)據(jù)類型只是進(jìn)行引用的傳遞,而沒有真實(shí)的創(chuàng)建一個(gè)新的對(duì)象,則認(rèn)為是淺拷貝。反之,在對(duì)引用數(shù)據(jù)類型進(jìn)行拷貝的時(shí)候,創(chuàng)建了一個(gè)新的對(duì)象,并且復(fù)制其內(nèi)的成員變量,則認(rèn)為是深拷貝

簡(jiǎn)單來說:

  • 淺拷貝:對(duì)基本數(shù)據(jù)類型進(jìn)行值傳遞,對(duì)引用數(shù)據(jù)類型進(jìn)行引用傳遞般的拷貝,此為淺拷貝
  • 深拷貝:對(duì)基本數(shù)據(jù)類型進(jìn)行值傳遞,對(duì)引用數(shù)據(jù)類型,創(chuàng)建一個(gè)新的對(duì)象,并復(fù)制其內(nèi)容,此為深拷貝。

BeanUtils

Apache 的 BeanUtils

beantutils 對(duì)于對(duì)象拷貝加了很多的檢驗(yàn),包括類型的轉(zhuǎn)換,甚至還會(huì)檢驗(yàn)對(duì)象所屬的類的可訪問性,可謂相當(dāng)復(fù)雜,這也造就了它的差勁的性能,在Java開發(fā)手冊(cè)中也提到盡量避免使用Apache 的 BeanUtils 工具類。

使用案例(注意參數(shù)的順序

public class PersonSource  {
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    // getters/setters omiited
}
public class PersonDest {
    private Integer id;
    private String username;
    private Integer age;
    // getters/setters omiited
}
public class TestApacheBeanUtils {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
       //下面只是用于單獨(dú)測(cè)試
        PersonSource personSource = new PersonSource(1, "pjmike", "12345", 21);
        PersonDest personDest = new PersonDest();
        BeanUtils.copyProperties(personDest,personSource);
        System.out.println("persondest: "+personDest);
    }
}
persondest: PersonDest{id=1, username='pjmike', age=21}

Spring 的 BeanUtils

spring下的BeanUtils也是使用 copyProperties方法進(jìn)行拷貝,只不過它的實(shí)現(xiàn)方式非常簡(jiǎn)單,就是對(duì)兩個(gè)對(duì)象中相同名字的屬性進(jìn)行簡(jiǎn)單的get/set,僅檢查屬性的可訪問性。

使用案例(注意參數(shù)的順序,和Apache相反)

public class TestSpringBeanUtils {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {

       //下面只是用于單獨(dú)測(cè)試
        PersonSource personSource = new PersonSource(1, "pjmike", "12345", 21);
        PersonDest personDest = new PersonDest();
        BeanUtils.copyProperties(personSource,personDest);
        System.out.println("persondest: "+personDest);
    }
}

小結(jié)

以上簡(jiǎn)要的分析兩種BeanUtils,因?yàn)锳pache下的BeanUtils性能較差,不建議使用,可以使用 Spring的BeanUtils,或者使用其他拷貝框架,比如 cglib BeanCopier,基于javassist的Orika等,這些也是非常優(yōu)秀的類庫(kù)。注意這種都是淺拷貝!!!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。