最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java?Bean所有拷貝方式使用方法及性能比較詳解

 更新時間:2025年10月22日 09:52:35   作者:猩火燎猿  
在Java開發(fā)中,常常需要將一個對象的屬性值拷貝到另一個對象中,下面這篇文章主要介紹了Java?Bean所有拷貝方式使用方法及性能比較的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

一、總體概述及比較

1. 手動拷貝

方式說明最原始也最靈活的方法,直接通過setter和getter手動賦值。

示例代碼

TargetBean target = new TargetBean();
target.setName(source.getName());
target.setAge(source.getAge());

優(yōu)點

  • 靈活性高,可以自定義轉(zhuǎn)換邏輯
  • 不依賴第三方庫

缺點

  • 代碼冗余,維護(hù)成本高
  • 屬性多時工作量大,易出錯

適用場景

  • 屬性復(fù)雜、轉(zhuǎn)換邏輯多樣時
  • 對性能和依賴有嚴(yán)格要求時

2. Java BeanUtils 工具類

2.1 Apache Commons BeanUtils

方式說明使用 org.apache.commons.beanutils.BeanUtils 進(jìn)行屬性拷貝。

示例代碼

import org.apache.commons.beanutils.BeanUtils;
BeanUtils.copyProperties(target, source);

優(yōu)點

  • 簡單易用
  • 支持不同類型的對象拷貝

缺點

  • 依賴反射,性能較低
  • 不支持基本類型,全部按字符串處理,類型轉(zhuǎn)換有限
  • 不支持嵌套對象深拷貝

適用場景

  • 屬性簡單、性能要求不高的場合

2.2 Spring BeanUtils

方式說明使用 org.springframework.beans.BeanUtils 進(jìn)行屬性拷貝。

示例代碼

import org.springframework.beans.BeanUtils;
BeanUtils.copyProperties(source, target);

優(yōu)點

  • 性能比 Apache BeanUtils 略高
  • 支持基本類型
  • Spring 項目中開箱即用

缺點

  • 依然是淺拷貝,不支持嵌套對象
  • 對屬性名和類型要求嚴(yán)格

適用場景

  • Spring 項目中,簡單Bean轉(zhuǎn)換

3. CGLIB BeanCopier

方式說明使用 CGLIB 的 BeanCopier,通過動態(tài)生成字節(jié)碼實現(xiàn)高性能拷貝。

示例代碼

import net.sf.cglib.beans.BeanCopier;
BeanCopier copier = BeanCopier.create(Source.class, Target.class, false);
copier.copy(source, target, null);

優(yōu)點

  • 性能高于反射方式
  • 支持同名同類型屬性的快速拷貝

缺點

  • 依賴CGLIB庫
  • 不支持類型轉(zhuǎn)換和嵌套對象
  • 代碼略繁瑣

適用場景

  • 需要批量高性能拷貝的場景

4. MapStruct

方式說明MapStruct 是編譯期代碼生成的Bean拷貝工具,支持復(fù)雜映射和自定義轉(zhuǎn)換。

示例代碼

@Mapper
public interface UserMapper {
    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
    TargetBean toTargetBean(SourceBean source);
}

使用:

TargetBean target = UserMapper.INSTANCE.toTargetBean(source);

優(yōu)點

  • 編譯期生成代碼,性能極高
  • 支持復(fù)雜屬性映射、類型轉(zhuǎn)換
  • 可自定義字段映射規(guī)則

缺點

  • 需要編寫接口和注解,學(xué)習(xí)成本略高
  • 需要編譯期插件支持

適用場景

  • 復(fù)雜對象轉(zhuǎn)換、大型項目、性能敏感場合

5. Dozer

方式說明Dozer 是一個支持深度拷貝的 Java Bean 到 Java Bean 的映射工具。

示例代碼

Mapper mapper = new DozerBeanMapper();
TargetBean target = mapper.map(source, TargetBean.class);

優(yōu)點

  • 支持深度拷貝
  • 支持復(fù)雜類型映射
  • 支持XML配置映射規(guī)則

缺點

  • 性能一般,反射實現(xiàn)
  • 配置和調(diào)試較復(fù)雜

適用場景

  • 需要深度拷貝和復(fù)雜映射的場景

6. ModelMapper

方式說明ModelMapper 也是一個Java Bean映射工具,支持復(fù)雜映射和類型轉(zhuǎn)換。

示例代碼

ModelMapper modelMapper = new ModelMapper();
TargetBean target = modelMapper.map(source, TargetBean.class);

優(yōu)點

  • 支持復(fù)雜映射和深拷貝
  • 支持自定義映射規(guī)則

缺點

  • 性能一般,反射實現(xiàn)
  • 配置略復(fù)雜

適用場景

  • 對轉(zhuǎn)換靈活性要求較高的場景

7. Lombok @Builder/@Data + 構(gòu)造方法

方式說明利用 Lombok 注解簡化代碼,通過構(gòu)造方法或Builder模式實現(xiàn)對象轉(zhuǎn)換。

示例代碼

TargetBean target = TargetBean.builder()
    .name(source.getName())
    .age(source.getAge())
    .build();

優(yōu)點

  • 代碼簡潔
  • 可自定義轉(zhuǎn)換邏輯

缺點

  • 需手動指定字段
  • 適合屬性較少、轉(zhuǎn)換邏輯簡單時

8. JSON序列化反序列化

方式說明通過Jackson、Gson等將對象轉(zhuǎn)為JSON再反序列化為目標(biāo)類型。

示例代碼

ObjectMapper mapper = new ObjectMapper();
TargetBean target = mapper.readValue(mapper.writeValueAsString(source), TargetBean.class);

優(yōu)點

  • 支持深度拷貝
  • 屬性名不一致時可通過注解映射

缺點

  • 性能較低
  • 依賴第三方庫
  • 不適合大批量高頻率場景

9. 總結(jié)對比表

方式性能深拷貝復(fù)雜映射依賴庫適用場景
手動拷貝支持支持靈活性強、屬性少
BeanUtilscommons/spring簡單Bean拷貝
CGLIB BeanCopiercglib大批量拷貝
MapStruct極高支持支持mapstruct大型項目、復(fù)雜轉(zhuǎn)換
Dozer一般支持支持dozer深拷貝、復(fù)雜映射
ModelMapper一般支持支持modelmapper靈活映射
Lombok Builder支持lombok屬性少、代碼簡潔
JSON序列化支持支持jackson/gson臨時、簡單深拷貝

10. 選擇建議

  • 簡單場景:Spring BeanUtils、CGLIB BeanCopier
  • 復(fù)雜映射:MapStruct、Dozer、ModelMapper
  • 深拷貝:Dozer、ModelMapper、JSON序列化
  • 性能敏感:MapStruct、CGLIB BeanCopier、手動拷貝
  • 靈活性高:手動拷貝、Lombok Builder

二、使用詳解

1、Spring BeanUtils 詳細(xì)用法

1.1. 基本用法

import org.springframework.beans.BeanUtils;

SourceBean source = new SourceBean();
TargetBean target = new TargetBean();
BeanUtils.copyProperties(source, target);

注意:屬性名和類型需完全一致,且只做淺拷貝(即對象屬性只拷貝引用)。

1.2. 拷貝部分屬性

可以指定忽略某些屬性:

BeanUtils.copyProperties(source, target, "password", "id");

1.3. 常見問題

  • 不支持深拷貝:嵌套對象只拷貝引用。
  • 類型不兼容會報錯:如 int 和 String 不能自動轉(zhuǎn)換。

2、Apache Commons BeanUtils 詳細(xì)用法

2.1. 基本用法

import org.apache.commons.beanutils.BeanUtils;

BeanUtils.copyProperties(target, source);

2.2. 類型轉(zhuǎn)換

BeanUtils會自動做一些類型轉(zhuǎn)換(如 String 轉(zhuǎn) int),但不支持復(fù)雜類型。

2.3. 性能問題

BeanUtils 采用反射,性能較低,不推薦在高頻場景下使用。

3、CGLIB BeanCopier 進(jìn)階用法

3.1. 基本用法

BeanCopier copier = BeanCopier.create(SourceBean.class, TargetBean.class, false);
copier.copy(source, target, null);

3.2. 支持自定義轉(zhuǎn)換

BeanCopier copier = BeanCopier.create(SourceBean.class, TargetBean.class, true);
copier.copy(source, target, (value, targetType, context) -> {
    // 自定義轉(zhuǎn)換邏輯
    if (value instanceof String && targetType == Integer.class) {
        return Integer.valueOf((String)value);
    }
    return value;
});

3.3. 性能優(yōu)勢

BeanCopier會動態(tài)生成字節(jié)碼,性能極高,適合大批量拷貝。

4、MapStruct 進(jìn)階用法

4.1. 基本映射

@Mapper
public interface UserMapper {
    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
    TargetBean toTargetBean(SourceBean source);
}

4.2. 字段名不一致映射

@Mapper
public interface UserMapper {
    @Mapping(source = "username", target = "name")
    TargetBean toTargetBean(SourceBean source);
}

4.3. 自定義類型轉(zhuǎn)換

@Mapper
public interface UserMapper {
    @Mapping(source = "age", target = "ageStr")
    TargetBean toTargetBean(SourceBean source);

    default String intToString(int age) {
        return String.valueOf(age);
    }
}

4.4. 集合轉(zhuǎn)換

List<TargetBean> toTargetBeanList(List<SourceBean> sourceList);

4.5. 注意事項

  • 需要在IDE或maven插件中開啟注解處理器。
  • 生成代碼后可直接調(diào)用,性能極高。

5、Dozer/ModelMapper 進(jìn)階用法

5.1. Dozer XML 配置

<mapping>
    <class-a>com.example.SourceBean</class-a>
    <class-b>com.example.TargetBean</class-b>
    <field>
        <a>username</a>
        <b>name</b>
    </field>
</mapping>

5.2. ModelMapper 映射規(guī)則

modelMapper.typeMap(SourceBean.class, TargetBean.class)
    .addMappings(mapper -> mapper.map(SourceBean::getUsername, TargetBean::setName));

5.3. 支持復(fù)雜對象和嵌套屬性

適合復(fù)雜領(lǐng)域模型轉(zhuǎn)換,但性能一般。

6、JSON序列化方式進(jìn)階

6.1. Jackson

ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(source);
TargetBean target = mapper.readValue(json, TargetBean.class);

6.2. Gson

Gson gson = new Gson();
String json = gson.toJson(source);
TargetBean target = gson.fromJson(json, TargetBean.class);

6.3. 注意事項

  • 適合臨時轉(zhuǎn)換或深拷貝,但性能較低。
  • 可通過注解如 @JsonProperty 實現(xiàn)字段名映射。

7、Lombok Builder/構(gòu)造方法進(jìn)階

7.1. Lombok簡化代碼

@Getter
@Setter
@Builder
public class TargetBean {
    private String name;
    private int age;
}

拷貝:

TargetBean target = TargetBean.builder()
    .name(source.getName())
    .age(source.getAge())
    .build();

7.2. 適合場景

  • 屬性較少、轉(zhuǎn)換邏輯簡單時
  • 代碼可讀性高,維護(hù)方便

8、實戰(zhàn)建議

  • 簡單DTO/VO轉(zhuǎn)換:優(yōu)先用Spring BeanUtils或CGLIB BeanCopier。
  • 復(fù)雜/多字段/類型轉(zhuǎn)換:優(yōu)先MapStruct。
  • 深拷貝或嵌套對象:Dozer、ModelMapper或JSON序列化。
  • 性能敏感批量轉(zhuǎn)換:CGLIB BeanCopier、MapStruct。
  • 自定義轉(zhuǎn)換邏輯多:手動拷貝或MapStruct自定義方法。

9、注意事項與最佳實踐

  • 避免在高并發(fā)場景用反射類工具(BeanUtils、Dozer等)
  • 字段名/類型不一致要選支持自定義映射的工具(MapStruct、Dozer、ModelMapper)。
  • 拷貝前后對象不可互相影響(深拷貝需求)時要選支持深拷貝的工具。
  • 轉(zhuǎn)換邏輯復(fù)雜時建議寫單元測試,避免數(shù)據(jù)丟失或錯誤

三、常見問題與解決辦法

1. 字段名不一致

問題:源對象和目標(biāo)對象字段名不同,常規(guī)工具(如Spring BeanUtils)無法自動拷貝。

解決方案

  • MapStruct支持@Mapping注解自定義字段映射。
  • DozerModelMapper可通過配置或API自定義映射。
  • 手動拷貝最靈活,直接賦值。

2. 類型不一致

問題:如源對象字段為String,目標(biāo)對象為Integer

解決方案

  • MapStruct可自定義轉(zhuǎn)換方法。
  • CGLIB BeanCopier可通過轉(zhuǎn)換器接口自定義類型轉(zhuǎn)換。
  • ModelMapper支持自定義轉(zhuǎn)換規(guī)則。

3. 嵌套對象或集合

問題:如源對象有嵌套對象或集合,淺拷貝只拷貝引用。

解決方案

  • Dozer、ModelMapper、JSON序列化支持深拷貝。
  • MapStruct支持嵌套對象和集合的轉(zhuǎn)換(可遞歸映射)。

4. 性能瓶頸

問題:反射類工具在大數(shù)據(jù)量場景下性能不足。

解決方案

  • MapStruct、CGLIB BeanCopier編譯期或字節(jié)碼級別實現(xiàn),性能極高。
  • 手動拷貝性能最佳,但開發(fā)成本高。

5. Null值處理

問題:拷貝時源對象字段為null,目標(biāo)對象是否需要覆蓋?

解決方案

  • BeanUtils默認(rèn)會拷貝null,可以通過擴展或自定義工具類實現(xiàn)跳過null。
  • MapStruct支持@Mapping(target = “xxx”, ignore = true)跳過指定字段。

四、性能對比與實測

工具性能(高/中/低)備注
手動拷貝極高無反射,代碼量大
CGLIB BeanCopier極高字節(jié)碼生成,適合高并發(fā)
MapStruct極高編譯期生成,適合復(fù)雜場景
Spring BeanUtils低~中反射實現(xiàn),適合簡單場景
Apache BeanUtils反射+類型轉(zhuǎn)換,性能最差
Dozer/ModelMapper反射+復(fù)雜映射,靈活性高
JSON序列化適合臨時深拷貝,性能低

實測建議

  • 單次拷貝或?qū)傩陨贂r性能差異不明顯,批量場景下優(yōu)先選MapStruct或CGLIB BeanCopier。
  • MapStruct適合字段復(fù)雜、類型多樣、性能敏感場景。
  • BeanUtils適合簡單、快速開發(fā)和原型驗證。

五、實際項目中的選擇建議

  • 微服務(wù)、領(lǐng)域模型轉(zhuǎn)換:推薦MapStruct(如DTO→Entity、VO→DTO)。
  • Spring項目簡單Bean拷貝:用Spring BeanUtils。
  • 需要深拷貝/嵌套對象:Dozer、ModelMapper或JSON序列化。
  • 批量高性能場景:CGLIB BeanCopier或MapStruct。
  • 自定義字段、類型轉(zhuǎn)換復(fù)雜:MapStruct或手動拷貝。

六、自定義拷貝場景舉例

1. 只拷貝非null字段

public static void copyNonNullProperties(Object src, Object target) {
    BeanWrapper srcWrap = new BeanWrapperImpl(src);
    BeanWrapper trgWrap = new BeanWrapperImpl(target);
    for (PropertyDescriptor pd : srcWrap.getPropertyDescriptors()) {
        Object value = srcWrap.getPropertyValue(pd.getName());
        if (value != null) {
            trgWrap.setPropertyValue(pd.getName(), value);
        }
    }
}

2. 字段名映射(MapStruct示例)

@Mapper
public interface MyMapper {
    @Mappings({
        @Mapping(source = "userName", target = "name"),
        @Mapping(source = "userAge", target = "age")
    })
    TargetBean toTarget(SourceBean source);
}

3. 嵌套對象拷貝(MapStruct示例)

@Mapper
public interface OrderMapper {
    OrderDTO toDTO(Order order);
    AddressDTO addressToDTO(Address address);
}

MapStruct會自動遞歸調(diào)用addressToDTO。

七、最佳實踐

  • 統(tǒng)一轉(zhuǎn)換入口:在項目中建議統(tǒng)一封裝Bean拷貝工具類,便于維護(hù)和擴展。
  • 單元測試覆蓋:復(fù)雜轉(zhuǎn)換邏輯務(wù)必寫單元測試,防止屬性丟失或錯誤。
  • 性能評估:批量轉(zhuǎn)換場景建議實際測評不同工具性能。
  • 異常處理:注意捕獲和處理轉(zhuǎn)換異常,避免因拷貝失敗影響業(yè)務(wù)流程。

八、參考工具封裝(示例)

public class BeanCopyUtil {
    public static <T> T copy(Object source, Class<T> clazz) {
        try {
            T target = clazz.newInstance();
            BeanUtils.copyProperties(source, target);
            return target;
        } catch (Exception e) {
            throw new RuntimeException("Bean copy failed", e);
        }
    }
}

可根據(jù)實際需要擴展支持MapStruct、CGLIB等。

到此這篇關(guān)于Java Bean所有拷貝方式使用方法及性能比較詳解的文章就介紹到這了,更多相關(guān)Java Bean所有拷貝方式使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot集成Lettuce客戶端操作Redis的實現(xiàn)

    SpringBoot集成Lettuce客戶端操作Redis的實現(xiàn)

    本文主要介紹了SpringBoot集成Lettuce客戶端操作Redis的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-11-11
  • 教你實現(xiàn)Java接口防刷

    教你實現(xiàn)Java接口防刷

    有些人會惡意提交,本文主要介紹了教你實現(xiàn)Java接口防刷,通過在一定時間內(nèi)限制同一用戶對同一個接口的請求次數(shù),具有一定的參考價值,感興趣的可以了解一下
    2024-05-05
  • Java中的鎖分類的詳細(xì)介紹

    Java中的鎖分類的詳細(xì)介紹

    這篇文章主要介紹了Java中的鎖分類的詳細(xì)介紹,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • 避免多個jar通過maven打包導(dǎo)致同名配置文件覆蓋沖突問題

    避免多個jar通過maven打包導(dǎo)致同名配置文件覆蓋沖突問題

    這篇文章主要介紹了避免多個jar通過maven打包導(dǎo)致同名配置文件覆蓋沖突問題,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • JAVA中常用的數(shù)據(jù)結(jié)構(gòu)和XML使用解析

    JAVA中常用的數(shù)據(jù)結(jié)構(gòu)和XML使用解析

    這篇文章主要介紹了JAVA中常用的數(shù)據(jù)結(jié)構(gòu)和XML使用,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • 解決SpringBoot log4j日志沒生成的問題

    解決SpringBoot log4j日志沒生成的問題

    這篇文章主要介紹了解決SpringBoot log4j日志沒生成的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • 詳解SpringBoot基于Dubbo和Seata的分布式事務(wù)解決方案

    詳解SpringBoot基于Dubbo和Seata的分布式事務(wù)解決方案

    這篇文章主要介紹了詳解SpringBoot基于Dubbo和Seata的分布式事務(wù)解決方案,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • Java數(shù)據(jù)類型實現(xiàn)自動與強制轉(zhuǎn)換的示例代碼

    Java數(shù)據(jù)類型實現(xiàn)自動與強制轉(zhuǎn)換的示例代碼

    Java數(shù)據(jù)類型之間的轉(zhuǎn)換有自動轉(zhuǎn)換和強制類型轉(zhuǎn)換,這篇文章主要給大家介紹Java數(shù)據(jù)類型如何實現(xiàn)自動轉(zhuǎn)換與強制轉(zhuǎn)換,需要的朋友可以參考下
    2023-05-05
  • Java的SPI機制以及基于SPI編程示例詳解

    Java的SPI機制以及基于SPI編程示例詳解

    這篇文章主要為大家介紹了Java的SPI機制以及基于SPI編程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • java中Hibernate面試知識點整理

    java中Hibernate面試知識點整理

    在本篇文章里小編給大家整理的是一篇關(guān)于java中Hibernate面試知識點整理內(nèi)容,有興趣的朋友們可以學(xué)習(xí)參考下。
    2021-01-01

最新評論

雅安市| 阿城市| 临海市| 宜良县| 平陆县| 土默特左旗| 迭部县| 怀宁县| 集贤县| 泸溪县| 垦利县| 昭通市| 长寿区| 开阳县| 湛江市| 德安县| 明光市| 克什克腾旗| 炉霍县| 彭山县| 东至县| 江西省| 额济纳旗| 连云港市| 沅陵县| 林口县| 丽江市| 德州市| 含山县| 新竹县| 额敏县| 玉门市| 名山县| 正蓝旗| 自贡市| 奈曼旗| 琼海市| 清水河县| 珠海市| 巴里| 霍山县|