博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java 开发中的对象拷贝
阅读量:4687 次
发布时间:2019-06-09

本文共 2971 字,大约阅读时间需要 9 分钟。

前言

在 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 毫秒。

源码如下图所示:

缓存源码:

自己写的简易版

1 public static void copyBean(Object target, Object source) throws IllegalAccessException, InstantiationException, NoSuchFieldException { 2         Class targetClass = target.getClass(); 3         Class sourceClass = source.getClass(); 4         // 获取目标类的所有参数 Field 5         Field[] fields = targetClass.getDeclaredFields(); 6         // 为目标类的每个参数设值 7         for (Field field : fields) { 8             // 如果数据源对象中存在对应的参数 9             Field sourceField = sourceClass.getDeclaredField(field.getName());10             if (null != sourceField) {11                 Field targetField = targetClass.getDeclaredField(field.getName());12                 targetField.setAccessible(true);13                 sourceField.setAccessible(true);14                 targetField.set(target, sourceField.get(source));15             }16         }17     }18 19     // 类似 Spring 的版本20     public static void copyBeanByMethod(Object target, Object source) throws IntrospectionException, InvocationTargetException, IllegalAccessException {21         Class targetClass = target.getClass();22         Class sourceClass = source.getClass();23         Field[] sourceFields = sourceClass.getDeclaredFields();24         for (Field field : sourceFields) {25             PropertyDescriptor targetProperty;26             try {27                 targetProperty = new PropertyDescriptor(field.getName(), targetClass);28             } catch (IntrospectionException e) {29                 continue;30             }31             Method writeMethod = targetProperty.getWriteMethod();32             if (writeMethod != null) {33                 PropertyDescriptor sourceProperty = new PropertyDescriptor(field.getName(), sourceClass);34                 Method readMethod = sourceProperty.getReadMethod();35                 if (!Modifier.isPublic(readMethod.getModifiers())) {36                     readMethod.setAccessible(true);37                 }38                 // 读取 source 中属性的值39                 Object value = readMethod.invoke(source);40                 if (!Modifier.isPublic(writeMethod.getModifiers())) {41                     writeMethod.setAccessible(true);42                 }43                 // 为 target 对应的属性赋值44                 writeMethod.invoke(target, value);45             }46         }47     }

小结

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

参考资料

[1]

转载于:https://www.cnblogs.com/zhengbin/p/7401745.html

你可能感兴趣的文章
鼠标经过切换图片
查看>>
流程控制 Day06
查看>>
Linux下安装Tomcat
查看>>
windows live writer 2012 0x80070643
查看>>
C程序的启动和终止
查看>>
tomcat 和MySQL的安装
查看>>
11.5 内部类
查看>>
Cosine Similarity
查看>>
halt和shutdown 的区别
查看>>
git常用操作
查看>>
京东SSO单点登陆实现分析
查看>>
u-boot启动第一阶段
查看>>
MySQL批量SQL插入性能优化
查看>>
定义列属性:null,default,PK,auto_increment
查看>>
用户画像展示
查看>>
C#中StreamReader读取中文出现乱码
查看>>
使用BufferedReader的时候出现的问题
查看>>
linux安装图形界面
查看>>
Android广播发送失败
查看>>
博弈论之入门小结
查看>>