对象拷贝类PropertyUtils,BeanUtils,BeanCopier.doc_第1页
对象拷贝类PropertyUtils,BeanUtils,BeanCopier.doc_第2页
对象拷贝类PropertyUtils,BeanUtils,BeanCopier.doc_第3页
对象拷贝类PropertyUtils,BeanUtils,BeanCopier.doc_第4页
对象拷贝类PropertyUtils,BeanUtils,BeanCopier.doc_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

对象拷贝类PropertyUtils,BeanUtils,BeanCopier功能简介业务系统中经常需要两个对象进行属性的拷贝,不能否认逐个的对象拷贝是最快速最安全的做法,但是当数据对象的属性字段数量超过程序员的容忍的程度,代码因此变得臃肿不堪,使用一些方便的对象拷贝工具类将是很好的选择。Apache的两个版本:(反射机制)mons.beanutils.PropertyUtils.copyProperties(Object dest, Object orig)mons.beanutils.BeanUtils.copyProperties(Object dest, Object orig)spring版本:(反射机制)org.springframework.beans.BeanUtils.copyProperties(Object source, Object target, Class editable, String ignoreProperties)cglib版本:(使用动态代理,效率高)net.sf.cglib.beans.BeanCopier.copy(Object paramObject1, Object paramObject2, Converter paramConverter))都使用静态类调用,最终转化虚拟机中两个单例的工具对象。publicBeanUtilsBean()this(newConvertUtilsBean(),newPropertyUtilsBean();ConvertUtilsBean可以通过ConvertUtils全局自定义注册。ConvertUtils.register(new DateConvert(),Java.util.Date.class);PropertyUtilsBean的copyProperties方法实现了拷贝的算法。1、 动态bean:orig instanceof DynaBean:Object value = (DynaBean)orig).get(name);然后把value复制到动态bean类2、 Map类型:orig instanceof Map:key值逐个拷贝3、 其他普通类:从beanInfo【每一个对象都有一个缓存的bean信息,包含属性字段等】取出name,然后把sourceClass和targetClass逐个拷贝类型:BeanCopiercopier = BeanCopier.create(source.getClass(), target.getClass(), false);copier.copy(source, target, null);Create对象过程:产生sourceClass-TargetClass的拷贝代理类,放入jvm中,所以创建的代理类的时候比较耗时。最好保证这个对象的单例模式,可以参照最后一部分的优化方案。创建过程:源代码见jdk:net.sf.cglib.beans.BeanCopier.Generator.generateClass(ClassVisitor)1、 获取sourceClass的所有public get 方法-PropertyDescriptor getters2、 获取TargetClass 的所有 public set 方法-PropertyDescriptor setters3、 遍历setters的每一个属性,执行4和54、 按setters的name生成sourceClass的所有setter方法-PropertyDescriptor getter【不符合javabean规范的类将会可能出现空指针异常】5、 PropertyDescriptor setters-PropertyDescriptor setter6、 将setter和getter名字和类型 配对,生成代理类的拷贝方法。Copy属性过程:调用生成的代理类,代理类的代码和手工操作的代码很类似,效率非常高。缺陷预防陷阱条件Apache- PropertyUtilsApache- BeanUtilsSpring- BeanUtilsCglib-BeanCopier是否可以扩展useConvete功能NOYesYesYes,但比较难用(sourceObject,targetObject)的顺序逆序逆序OKOK对sourceObject特殊属性的限制:(Date,BigDecimal等)【见备注1】OKNO,异常出错OKOK相同属性名,且类型不匹配时候的处理【见备注2】异常,拷贝部分属性,非常危险OK,并能进行初级转换,Long和Integer互转异常,拷贝部分属性OK,但是该属性不拷贝Get和set方法不匹配的处理【见备注3】OKOKOK创建拷贝的时候报错,无法拷贝任何属性(当且仅当sourceClass的get方法超过set方法)对targetObject特殊属性的限制:(Date,BigDecimal等)原因:dateTimeConveter的conveter没有对null值的处理public classErrorBeanUtilObject /此处省略getter,setter方法privateStringname;privatejava.util.Datedate;public classErrorBeanUtilsTest public static voidmain(String args)throwsThrowable ErrorBeanUtilObject from =newErrorBeanUtilObject(); ErrorBeanUtilObject to =newErrorBeanUtilObject(); /from.setDate(newjava.util.Date(); from.setName(TTTT); mons.beanutils.BeanUtils.copyProperties(to, from);/如果from.setDate去掉,此处出现conveter异常 System.out.println(ToStringBuilder.reflectionToString(from); System.out.println(ToStringBuilder.reflectionToString(to); 相同属性名,且类型不匹配时候的处理原因:这两个工具类不支持同名异类型的匹配 !【包装类Long和原始数据类型long是可以的】public classTargetClass /此处省略getter,setter方法privateLong num;privateString name;public classTargetClass /此处省略getter,setter方法privateLong num;privateString name;public classErrorPropertyUtilsTest public static voidmain(String args)throwsIllegalAccessException, InvocationTargetException, NoSuchMethodException SourceClass from =newSourceClass(); from.setNum(1); from.setName(name); TargetClass to =newTargetClass(); mons.beanutils.PropertyUtils.copyProperties(to, from); /抛出参数不匹配异常 org.springframework.beans.BeanUtils.copyProperties(from, to);/抛出参数不匹配异常 System.out.println(ToStringBuilder.reflectionToString(from); System.out.println(ToStringBuilder.reflectionToString(to); Get和set方法不匹配的处理public classErrorBeanCopierTest /* * 从该用例看出BeanCopier.create的target.class 的每一个get方法必须有队形的set方法 *paramargs */public static voidmain(String args) BeanCopier copier = BeanCopier.create(UnSatifisedBeanCopierObject.class, SourceClass.class,false); copier = BeanCopier.create(SourceClass.class, UnSatifisedBeanCopierObject.class,false); /此处抛出异常创建 classUnSatifisedBeanCopierObject privateString name;privateLong num;publicString getName() returnname; public voidsetName(String name) = name; publicLong getNum() returnnum; / public void setNum(Longnum) / this.num =num;/ 优化方案的beanUtils的拷贝属性,注册一些新的类型转换public class BeanUtilsEx extends BeanUtils public static void copyProperties(Object dest, Object orig) try BeanUtils.copyProperties(dest, orig); catch (IllegalAccessException ex) ex.printStackTrace(); catch (InvocationTargetException ex) ex.printStackTrace(); static ConvertUtils.register(new DateConvert(), java.util.Date.class); ConvertUtils.register(new DateConvert(), java.sql.Date.class); ConvertUtils.register(new BigDecimalConvert(), BigDecimal.class); 将beancopier做成静态类,方便拷贝public classBeanCopierUtils public staticMapbeanCopierMap=newHashMap();public static voidcopyProperties(Object source, Object target) String beanKey =generateKey(source.getClass(), target.getClass(); BeanCopier copier =null;if(!beanCopierMap.containsKey(beanKey) copier = BeanCopier.create(source.getClass(), target.getClass(),false);beanCopierMap.put(beanKey, copier); else copier =beanCopierMap.get(beanKey); copier.copy(source, target,null); private staticString generateKey(Class class1,Classclass2)returnclass1.toString() + class2.toString(); 修复beanCopier对set方法强限制的约束改写net.sf.cglib.beans.BeanCopier.Generator.generateClass(ClassVisitor)方法将133行的

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论