Java Spring BeanUtils 拷贝多个源对象 source 到目标对象 target

简介: Spring BeanUtils可简化Java Bean属性拷贝,避免冗余get/set代码。支持忽略字段、限制类属性等操作,性能优于Apache工具,但需注意多源拷贝时的顺序问题,防止属性覆盖。

背景信息

最近在工作中,由于对象有太多的属性需要get,set ,对所有属性都这样操作的话,除了多余敲很多没有价值的代码量,还有点耽误时间。这个时候就考虑到可以使用 Spring BeanUtils 工具来直接实现把源对象 拷贝 到目标对象的操作,从而大大的节省人工通过get,set 方法来实现属性值获取与赋值的操作时间。

Spring BeanUtils

Spring BeanUtils 是 Spring Framework 核心模块中的一个实用工具类,主要用于 Java Bean 的属性操作和对象拷贝。它相比 Apache Commons BeanUtils 更加轻量且性能更好。

pom文件配置

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-beans</artifactId>
    <version>5.3.0</version>
</dependency>

主要优势

  • 无额外依赖:Spring 项目天然集成,无需额外引入依赖
  • 性能优化:相比 Apache Commons BeanUtils 性能更好
  • 类型安全:更强的类型检查机制
  • 简单易用:API 设计简洁明了

常用方法

  1. copyProperties(Object source, Object target)
    将源对象中的属性值拷贝到目标对象中,只要属性名相同。
  2. copyProperties(Object source, Object target, Class<?> editable)
    限制只拷贝editable类中定义的属性(通常用于限制只拷贝特定类中的属性,避免拷贝父类属性)。
  3. copyProperties(Object source, Object target, String... ignoreProperties)
    拷贝属性,但忽略指定的属性名。
  4. copyProperties(Object source, Object target, Class<?> editable, String... ignoreProperties)
    拷贝对象内容,限制只拷贝editable类中定义的属性,忽略指定的属性名

与 Apache Commons BeanUtils 的区别

  1. Spring BeanUtils 不提供类型转换,而 Apache Commons BeanUtils 提供了默认的类型转换(但效率较低)。
  2. Spring BeanUtils 在拷贝属性时,如果遇到类型不匹配,会抛出异常,而 Apache Commons BeanUtils 会尝试进行类型转换,如果转换失败则抛出异常。
  3. 性能上,Spring BeanUtils 通常比 Apache Commons BeanUtils 快,因为它没有使用反射缓存,而且没有类型转换的开销(但要求属性类型必须匹配)。

举例说明

这里我们准备三个对象:Student  , Score  , Info 对象,目标就是将 Student 和 Score 对象中的属性值拷贝到 Info 对象中

package org.example;

public class Student {
    private String name;
    private int age;
    private String sex;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}
package org.example;

public class Score {
    private int score;
    private String name;

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
package org.example;

public class Info {
    private String name;
    private int age;
    private String sex;
    private int score;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }
}

下面我们开始测试,这里我们通过以下代码给 Student 属性赋值,给 Score 属性赋值,赋值后拷贝给 目标对象 Info 打印Info 对象的属性值信息

    public static void main(String[] args) throws Exception {
        Student student = new Student();
        student.setAge(10);
        student.setName("aa");
        student.setSex("man");
        Score score = new Score();
        score.setScore(100);
        Info dest = new Info();
        BeanUtils.copyProperties( score,dest);
        BeanUtils.copyProperties(student,dest);
        System.out.println(JSON.toJSONString(dest));
    }

执行结果如图

image.png

这里我们可以看到我们的字段属性都已经拷贝成功了。但是这里我有一个地方需要说明一下,对于上面的 Score 对象,我们看到也有属性值 name 字段,同时在 main 方法中没有对 Score 对象的 name 字段赋值,那么此时如果拷贝的顺序有变化,比如对上面的 main 方法进行下面的调整

image.png

先将 Student 对象拷贝到 Info 对象,再将 Score 对象拷贝到 Info 对象,那么此时由于 Score 对象中也有 name 字段属性,且在 main 方法中没有赋值,且 后执行的拷贝,那么此时 Score 对象中的空 name 就会覆盖 前面对象 Student 对象的 name 字段属性值,结果就会导致 name 字段属性值丢失,就像这样的效果

image.png

因此在使用时,如果对多个源对象拷贝到目标对象操作,需要注意拷贝顺序,防止由此带来的字段属性值丢失,且不好排查。

相关文章
|
2月前
|
安全
UUID 与 MD5 重复概率深度分析
UUID与MD5均生成128位值,理论碰撞概率相同。但UUIDv4基于随机生成,实际重复概率极低,适合唯一标识;MD5依赖输入数据,存在已知安全漏洞,碰撞风险更高,不推荐用于安全敏感场景。
|
2月前
|
数据采集 监控 API
告别手动埋点!Android 无侵入式数据采集方案深度解析
传统的Android应用监控方案需要开发者在代码中手动添加埋点,不仅侵入性强、工作量大,还难以维护。本文深入探讨了基于字节码插桩技术的无侵入式数据采集方案,通过Gradle插件 + AGP API + ASM的技术组合,实现对应用性能、用户行为、网络请求等全方位监控,真正做到零侵入、易集成、高稳定。
514 42
|
2月前
|
机器学习/深度学习 数据可视化 算法
sklearn 特征选择实战:用 RFE 找到最优特征组合
特征越多模型未必越好,过多特征易导致过拟合、训练慢、难解释。递归特征消除(RFE)通过反复训练与特征评分,逐步剔除不重要特征,提升模型泛化能力与效率。本文详解RFE原理,并用scikit-learn实战葡萄酒数据集,展示如何结合逻辑回归与随机森林进行特征选择,比较不同模型的筛选差异,并通过RFECV自动确定最优特征数量,辅以可视化分析,帮助构建更简洁、高效、可解释的模型。
209 1
sklearn 特征选择实战:用 RFE 找到最优特征组合
|
2月前
|
存储 人工智能 安全
揭秘 MCP Streamable HTTP 协议亲和性的技术内幕
函数计算推出MCP Streamable HTTP亲和机制,支持会话级请求绑定,解决传统Serverless对会话应用支持不足的问题。实现高效生命周期控制,并支持Bearer认证,助力开发者构建更稳定、安全、高性能的AI应用服务。
622 25
|
2月前
|
人工智能 监控 安全
提效40%?揭秘AI驱动的支付方式“一键接入”系统
本项目构建AI驱动的研发提效系统,通过Qwen Coder与MCP工具链协同,实现跨境支付渠道接入的自动化闭环。采用多智能体协作模式,结合结构化Prompt、任务拆解、流程管控与安全约束,显著提升研发效率与交付质量,探索大模型在复杂业务场景下的高采纳率编码实践。
428 26
提效40%?揭秘AI驱动的支付方式“一键接入”系统
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
UI-Ins:让 GUI 智能体真正“看懂”用户指令的新范式
通义实验室联合人大发布全新GUI Grounding模型UI-Ins,首创“指令即推理”范式,通过多视角动态推理实现SOTA性能,在五大基准全面领先,支持开源复现与应用。
547 1
|
2月前
|
SQL 人工智能 关系型数据库
AI Agent的未来之争:任务规划,该由人主导还是AI自主?——阿里云RDS AI助手的最佳实践
AI Agent的规划能力需权衡自主与人工。阿里云RDS AI助手实践表明:开放场景可由大模型自主规划,高频垂直场景则宜采用人工SOP驱动,结合案例库与混合架构,实现稳定、可解释的企业级应用,推动AI从“能聊”走向“能用”。
883 39
AI Agent的未来之争:任务规划,该由人主导还是AI自主?——阿里云RDS AI助手的最佳实践
|
2月前
|
人工智能 安全 人机交互
溯源技术革命:新型数字水印如何让数据“开口说话”,指认泄密源头?
当敏感信息遭偷拍、打印外泄或录音外传,隐形数字水印如“数据守护者”悄然溯源,精准锁定泄密源头。跨屏幕、纸质、音视频等多介质,实现“电-光-电”“电-纸-电”“电-空-电”全链路追踪。从军工到金融,从会议到协作,水印技术正构筑数据安全“最后一公里”防线。AIGC时代,更将融合AI与区块链,守护数字真实性。
|
2月前
|
数据可视化 算法 安全
智能体赋能企业管理:数据驱动决策的治理现代化实践
北京某互联网公司HR每月核算百人绩效耗时3天、准确率仅85%。引入“智能体来了”HR智能系统后,通过API整合Jira、企业微信、CRM数据,采用Drools规则引擎实现考核逻辑可配置,ECharts可视化分析,将核算压缩至2小时,准确率达99%,离职预测准确率82%,助力企业迈向数据驱动管理,符合国家智能化升级与数据安全规范要求。
|
2月前
|
数据采集 人工智能 物联网
国产AI封神!炒股狂赚40%碾压对手 教你微调Qwen3打造专属金融分析师
国产AI在实盘炒股中大放异彩,DeepSeek与Qwen3收益率最高超60%,碾压国际大模型。本文教你用LLaMA Factory平台微调Qwen3-VL-30B,打造专属多模态金融分析师,实现趋势研判、财报分析等专业能力,赋能投资决策。
835 156
国产AI封神!炒股狂赚40%碾压对手 教你微调Qwen3打造专属金融分析师