前言

在 Java 开发中,很多时候需要将两个属性基本相同的对象进行属性复制,比如 DO 转 VO等等。

本文主要介绍自己实现的简易拷贝工具类与 Spring 提供的属性拷贝的对比。

Spring 提供的属性拷贝

在 Spring 中直接调用 BeanUtils.copyProperties();即可。

它的核心通过循环 target 的所有方法名,然后在 source 中找到对应的方法名,最后通过反射从 source 中获取并写入 target 中。

Spring 没有通过 java.lang.reflect 中的 Field 来做,而是通过 java.beans 中的 PropertyDescriptor 来实现。

  补充:PropertyDescriptor 描述 Java Bean 通过一对存储器方法导出的一个属性。

通过 PropertyDescriptor 提供的 getReadMethod() 和 getWriteMethod() 方法,可以方便的获取到读取、写入属性值的方法(Method)。

同时,Spring 也做了缓存,在测试中,第一次的对象拷贝用时 300+ 毫秒,之后在缓存中获取,用时 0 毫秒。

源码如下图所示:

缓存源码:

自己写的简易版

 public static void copyBean(Object target, Object source) throws IllegalAccessException, InstantiationException, NoSuchFieldException {
Class targetClass = target.getClass();
Class sourceClass = source.getClass();
// 获取目标类的所有参数 Field
Field[] fields = targetClass.getDeclaredFields();
// 为目标类的每个参数设值
for (Field field : fields) {
// 如果数据源对象中存在对应的参数
Field sourceField = sourceClass.getDeclaredField(field.getName());
if (null != sourceField) {
Field targetField = targetClass.getDeclaredField(field.getName());
targetField.setAccessible(true);
sourceField.setAccessible(true);
targetField.set(target, sourceField.get(source));
}
}
} // 类似 Spring 的版本
public static void copyBeanByMethod(Object target, Object source) throws IntrospectionException, InvocationTargetException, IllegalAccessException {
Class targetClass = target.getClass();
Class sourceClass = source.getClass();
Field[] sourceFields = sourceClass.getDeclaredFields();
for (Field field : sourceFields) {
PropertyDescriptor targetProperty;
try {
targetProperty = new PropertyDescriptor(field.getName(), targetClass);
} catch (IntrospectionException e) {
continue;
}
Method writeMethod = targetProperty.getWriteMethod();
if (writeMethod != null) {
PropertyDescriptor sourceProperty = new PropertyDescriptor(field.getName(), sourceClass);
Method readMethod = sourceProperty.getReadMethod();
if (!Modifier.isPublic(readMethod.getModifiers())) {
readMethod.setAccessible(true);
}
// 读取 source 中属性的值
Object value = readMethod.invoke(source);
if (!Modifier.isPublic(writeMethod.getModifiers())) {
writeMethod.setAccessible(true);
}
// 为 target 对应的属性赋值
writeMethod.invoke(target, value);
}
}
}

小结

Spring 所提供的属性拷贝虽然第一次效率较低,但随后如果再次使用相同的 source 进行拷贝,则 Spring 会通过第一次拷贝保存的缓存来直接进行快速的拷贝

参考资料

[1] 谈谈 Java 开发中的对象拷贝

Java 开发中的对象拷贝的更多相关文章

  1. 编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则)

    编写高质量代码:改善Java程序的151个建议(第一章:JAVA开发中通用的方法和准则) 目录 建议1: 不要在常量和变量中出现易混淆的字母 建议2: 莫让常量蜕变成变量 建议3: 三元操作符的类型务 ...

  2. Java开发中文件读取方式总结

    JAVA开发中,免不了要读文件操作,读取文件,首先就需要获取文件的路径. 路径分为绝对路径和相对路径. 在文件系统中,绝对路径都是以盘符开始的,例如C:\abc\1.txt. 什么是相对路径呢?相对路 ...

  3. Java开发中常见的危险信号(上)

    本文来源于我在InfoQ中文站原创的文章,原文地址是:http://www.infoq.com/cn/news/2013/12/common-red-flags-in-java-1 Dustin Ma ...

  4. [ 转载 ] Java开发中的23种设计模式详解(转)

    Java开发中的23种设计模式详解(转)   设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类 ...

  5. Java开发中代码规范有哪些?

    Java开发中所要遵守的编码规范大体上有如下7点.命名规范.注释规范.缩进排版规范.文件名规范.声明规范.语句规范以及编程规范. 1.命名规范 (1)所有的标示符都只能用ASCⅡ字母(A-Z或a-z) ...

  6. EBS OAF开发中实体对象和视图对象的属性设置器

    EBS OAF开发中实体对象和视图对象的属性设置器 (版权声明.本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处:否则请与本人联系,违者必究) 源文: Home > Oracle ...

  7. Java开发中常用jar包整理及使用

    本文整理了我自己在Java开发中常用的jar包以及常用的API记录. <!-- https://mvnrepository.com/artifact/org.apache.commons/com ...

  8. Java开发中RMI和webservice区别和应用领域

    Java开发中RMI和webservice区别和应用领域 一.RMI和webservice区别和联系 0. 首先,都是远程调用技术. 1. RMI是在TCP协议上传递可序列化的java对象(使用Str ...

  9. JAVA开发中相对路径,绝对路径全面总结

    JAVA开发中相对路径,绝对路径全面总结 博客分类: Java综合 JavaJSP应用服务器Servlet网络应用 1.基本概念的理解 绝对路径:绝对路径就是你的主页上的文件或目录在硬盘上真正的路径, ...

随机推荐

  1. python学习笔记——爬虫中提取网页中的信息

    1 数据类型 网页中的数据类型可分为结构化数据.半结构化数据.非结构化数据三种 1.1 结构化数据 常见的是MySQL,表现为二维形式的数据 1.2 半结构化数据 是结构化数据的一种形式,并不符合关系 ...

  2. Eclipse中Ant的配置与测试

    在Eclipse中使用Ant Ant是Java平台下非常棒的批处理命令执行程序,能非常方便地自动完成编译,测试,打包,部署等等一系列任务,大大提高开发效率.如果你现在还没有开始使用Ant,那就要赶快开 ...

  3. Intent----android中的伟大邮差

    在android中,intent就像是一个邮差,辛勤高效的在各个组件之间来回穿梭.我们可以通过它启动一个Activity或者Service,或者是发送给广播组件,又或者是与后台的Service进行通信 ...

  4. 【Android】图片切角,切指定的边。

    公司的项目,UI和应用都是我自己做的.前几天设计了一个UI,出现了半边圆角的情况,如下图片所示.图片都来自服务器,肯定不能要求返回的图片按这个格式,必须在应用端对图片进行切角. Google了好久,发 ...

  5. 安装和配置SharePoint 2013 Workflow

    SharePoint 2013中的工作流概述 在SharePoint 2013中,Workflow(建立在Windows Workflow Foundation 4.5)和WCF承载在Workflow ...

  6. 关于switch语句中使用String类型的实现原理

    在Java 7 以后,switch语句可以用作String类型上. 从本质来讲,switch对字符串的支持,其实也是int类型值的匹配.它的实现原理如下: 通过对case后面的String对象调用ha ...

  7. 【转载】Android 关于arm64-v8a、armeabi-v7a、armeabi、x86下的so文件兼容问题

    转自:[欧阳鹏]http://blog.csdn.net/ouyang_peng Android 设备的CPU类型(通常称为”ABIs”) armeabiv-v7a: 第7代及以上的 ARM 处理器. ...

  8. AR模型与数据平稳性之间的关系

    作者:桂. 时间:2017-12-19  21:39:08 链接:http://www.cnblogs.com/xingshansi/p/8068021.html 前言 前几天碰到一个序列分析的问题, ...

  9. Viewpager 去掉两侧的光晕效果

    方案1: viewPager.setOverScrollMode(viewPager.OVER_SCROLL_NEVER); 方案2:通过反射的办法,直接操作具体控件具体的控件 private voi ...

  10. 绕过chrome的弹窗拦截机制

    在chrome的安全机制里面,非用户触发的window.open方法,是会被拦截的.举个例子: var btn = $('#btn'); btn.click(function () { //不会被拦截 ...