编程语言
首页 > 编程语言> > Java对象拷贝原理剖析及最佳实践

Java对象拷贝原理剖析及最佳实践

作者:互联网

1序言

目标复制,是在研发流程中,避不开的一个过程,既存在Po、Dto、Do、Vo每个表现层数据库的变换,也存在系统交互如实例化、反序列化。

Java对象复制分成深拷贝和浅拷贝,现阶段常见的特性复制专用工具,包含Apache的BeanUtils、Spring的BeanUtils、Cglib的BeanCopier、mapstruct全是浅拷贝。

1.1深拷贝

深拷贝:对基本数据类型开展值传递,对引用数据类型,建立一个新的目标,并拷贝内容称之为深拷贝。

深拷贝普遍有如下四种控制方式:

对象

Serializable实例化

完成Cloneable接口

JSON实例化

1.2浅拷贝

浅拷贝:对基本数据类型开展值传递,对引用数据类型开展引用传递一样的复制称之为浅拷贝。根据完成Cloneabe接口并重新写过Object类中的clone()方式能够实现浅复制。

2常见目标复制专用工具基本原理分析及性能对比

现阶段常见的特性复制专用工具,包含Apache的BeanUtils、Spring的BeanUtils、Cglib的BeanCopier、mapstruct。

ApacheBeanUtils:BeanUtils是Apachecommons部件里边中的一员,由Apache给予的一套开源系统api,用以简单化对javaBean操作,可以对基本类型全自动变换。

SpringBeanUtils:BeanUtils是spring框架下带有的专用工具,在org.springframework.beans包下,spring新项目能够直接用。

CglibBeanCopier:cglib(CodeGenerationLibrary)是一个强悍的、性能卓越、高质量代码生成类库,BeanCopier依托cglib的字节码增强能力,动态生成实现类,进行对象复制。

mapstruct:mapstruct是一个Java注解Cpu,用以形成类型安全的Bean投射类,在建立时,依据注释形成实现类,进行目标复制。

2.1基本原理剖析

2.1.1ApacheBeanUtils

使用方法:BeanUtils.copyProperties(target,source);

BeanUtils.copyProperties目标复制的关键编码如下所示:

//1.获得源对象的属性叙述

PropertyDescriptor[]origDescriptors=this.getPropertyUtils().getPropertyDescriptors(orig);

PropertyDescriptor[]temp=origDescriptors;

intlength=origDescriptors.length;

Stringname;

Objectvalue;

//2.循环系统获得源目标每一个特性,设定目标对象基础属性

for(inti=0;iPropertyDescriptororigDescriptor=temp[i];

name=origDescriptor.getName();

//3.校检源目标字段名能读切目标对象该字段名应写

if(!"class".equals(name)&&this.getPropertyUtils().isReadable(orig,name)&&this.getPropertyUtils().isWriteable(dest,name)){

try{

//4.获得源目标字段值

value=this.getPropertyUtils().getSimpleProperty(orig,name);

//5.复制特性

this.copyProperty(dest,name,value);

}catch(NoSuchMethodExceptionvar10){

}

}

}

循环遍历源对象每一个特性,对于每一个特性,复制步骤为:

校检由来类字段名是否可以读isReadable

校检总体目标类字段名是否可以写isWriteable

获得由来类字段名基础属性getSimpleProperty

获得总体目标类字段种类type,然后进行数据转换

设定总体目标类字段值

因为一个字段复制时每一个阶段都是会启用PropertyUtilsBean.getPropertyDescriptor获得特性配备,而此方法根据for循环获得类字段名特性,严重危害复制高效率。

获得字段名特性配备的关键编码如下所示:

PropertyDescriptor[]descriptors=this.getPropertyDescriptors(bean);

if(descriptors!=null){

for(inti=0;iif(name.equals(descriptors[i].getName())){

returndescriptors[i];

}

}

}

2.1.2SpringBeanUtils

使用方法:BeanUtils.copyProperties(source,target);

BeanUtils.copyProperties关键编码如下所示:

PropertyDescriptor[]targetPds=getPropertyDescriptors(actualEditable);

ListignoreList=ignoreProperties!=null?Arrays.asList(ignoreProperties):null;

PropertyDescriptor[]arr$=targetPds;

intlen$=targetPds.length;

for(inti$=0;i$PropertyDescriptortargetPd=arr$[i$];

MethodwriteMethod=targetPd.getWriteMethod();

if(writeMethod!=null&&(ignoreList==null||!ignoreList.contains(targetPd.getName()))){

PropertyDescriptorsourcePd=getPropertyDescriptor(source.getClass(),targetPd.getName());

if(sourcePd!=null){

MethodreadMethod=sourcePd.getReadMethod();

if(readMethod!=null&&ClassUtils.isAssignable(writeMethod.getParameterTypes()[0],readMethod.getReturnType())){

try{

if(!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())){

readMethod.setAccessible(true);

}

Objectvalue=readMethod.invoke(source);

if(!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())){

writeMethod.setAccessible(true);

}

writeMethod.invoke(target,value);

}catch(Throwablevar15){

thrownewFatalBeanException("Couldnotcopyproperty'"+targetPd.getName()+"'fromsourcetotarget",var15);

}

}

}

}

}

标签:java,数据库,作用,微信,淘宝,管理数据,安装配置,MySQL
来源: