spring\spring boot拷贝实体的工具类---BeanObjectCopyUtils
2023-02-25 18:21:50 时间
目录
前言:
介绍一个实用的bean对象实体类的拷贝工具,主要封装了两个方法进行实体类的字符拷贝处理,单个实体以及实体列表的拷贝操作。
第一步:引用的核心类:
BeanUtils
核心的思想是根据反射进行类中成员变量的赋值操作,本文一共实现了两种方式的实体拷贝方法:
第一种:单个实体的拷贝方法
第二种:列表类的实体拷贝方法
第二步:核心方法的介绍:
核心方法一,介绍了实例化的操作:
/** @deprecated */
@Deprecated
public static <T> T instantiate(Class<T> clazz) throws BeanInstantiationException {
Assert.notNull(clazz, "Class must not be null");
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
} else {
try {
return clazz.newInstance();
} catch (InstantiationException var2) {
throw new BeanInstantiationException(clazz, "Is it an abstract class?", var2);
} catch (IllegalAccessException var3) {
throw new BeanInstantiationException(clazz, "Is the constructor accessible?", var3);
}
}
}
核心方法二、拷贝属性的方法:
public static void copyProperties(Object source, Object target) throws BeansException {
copyProperties(source, target, (Class)null, (String[])null);
}
核心方法三、具体的实现的方法:
private static void copyProperties(Object source, Object target, @Nullable Class<?> editable, @Nullable String... ignoreProperties) throws BeansException {
Assert.notNull(source, "Source must not be null");
Assert.notNull(target, "Target must not be null");
Class<?> actualEditable = target.getClass();
if (editable != null) {
if (!editable.isInstance(target)) {
throw new IllegalArgumentException("Target class [" + target.getClass().getName() + "] not assignable to Editable class [" + editable.getName() + "]");
}
actualEditable = editable;
}
PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
List<String> ignoreList = ignoreProperties != null ? Arrays.asList(ignoreProperties) : null;
PropertyDescriptor[] var7 = targetPds;
int var8 = targetPds.length;
for(int var9 = 0; var9 < var8; ++var9) {
PropertyDescriptor targetPd = var7[var9];
Method writeMethod = targetPd.getWriteMethod();
if (writeMethod != null && (ignoreList == null || !ignoreList.contains(targetPd.getName()))) {
PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
if (sourcePd != null) {
Method readMethod = sourcePd.getReadMethod();
if (readMethod != null && ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
try {
if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
readMethod.setAccessible(true);
}
Object value = readMethod.invoke(source);
if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
writeMethod.setAccessible(true);
}
writeMethod.invoke(target, value);
} catch (Throwable var15) {
throw new FatalBeanException("Could not copy property '" + targetPd.getName() + "' from source to target", var15);
}
}
}
}
}
}
这个也是spring-bean的官方方式,使用起来也比较放心,源码的逻辑看着是先反射成class,然后获取力量吗的所有的属性值,循环进行属性值的赋值操作。
第三步:项目中创建工具类的核心代码
实际的应用代码中只需要下面的方法即可,上面是讲解了一些源码的逻辑。
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
/**
* 对象拷贝工具
* @author DELL
* @version 1.0
*/
public class BeanObjectCopyUtils{
private static Logger LOGGER = LoggerFactory.getLogger( BeanObjectCopyUtils.class );
/**
* 拷贝对象
* @param desObj 目标对象
* @param origObj 源对象
* @return desObj 目标对象
*/
public static <T,E> T copyObject(T desObj, E origObj){
if(origObj!=null && desObj!=null){
try {
BeanUtils.copyProperties(origObj, desObj);
}
catch (Exception e) {
LOGGER.error("object copy error",e);
throw new RuntimeException("object copy error",e);
}
}
return desObj;
}
/**
* 拷贝List对象到另一个list对象
* @param desClass 源List对象
* @param sourceList 目标List对象
* @return List
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public static <T> List<T> copyListObjToListObj(Class<T> desClass, List sourceList){
List desList=new ArrayList();
if(sourceList!=null){
for(int i=0; i<sourceList.size(); i++){
try {
Object sourceObj = sourceList.get(i);
Object desObj = desClass.newInstance();
BeanUtils.copyProperties(sourceObj, desObj);
desList.add(desObj);
}
catch (Exception e) {
LOGGER.error("list copy error",e);
throw new RuntimeException("list copy error",e);
}
}
}
return desList;
}
使用方法一、单个实体类的拷贝操作;
VoucherPostBaseBo vouchPostRecordBO = BeanObjectCopyUtils.copyObject(new VoucherPostBaseBo(), vouchPostRecordVO);
使用方法二、多个实体类(实体类列表的拷贝操作)
List<VoucherPostBaseBo> vouchPostRecordBO = BeanObjectCopyUtils.copyListObjToListObj(VoucherPostBaseBo.class, vouchPostRecordVO);
最后总结:
在封装一些工具类的时候,最好是使用一些官方定义的方法进行二次封装处理,这样有以下的好处,第一,可以保证封装方法的稳定性、安全性;第二,封装的方法之后,可以进行一些根据项目的实际情况进行特殊的处理,比如说日志的处理,报警的处理等等
相关文章
- Jgit的使用笔记
- 利用Github Action实现Tornadofx/JavaFx打包
- 叹息!GitHub Trending 即将成为历史!
- 微软软了?开源社区讨论炸锅,GitHub CEO 亲自来答
- GitHub Trending 列表频现重复项,前后端都没去重?
- Photoshop Elements 2021版本软件安装教程(mac+windows全版本都有)
- (ps全版本)Photoshop 2020的安装与破解教程(mac+windows全版本都有)
- (ps全版本)Photoshop cc2018的安装与破解教程(mac+windows全版本,包括2023
- 环境搭建:Oracle GoldenGate 大数据迁移到 Redshift/Flat file/Flume/Kafka测试流程
- 每个开发人员都要掌握的:最小 Linux 基础课
- 来撸羊毛了!Windows 环境下 Hexo 博客搭建,并部署到 GitHub Pages
- 超实用!手把手入门 MongoDB:这些坑点请一定远离
- 【GitHub日报】22-10-09 zustand、neovim、webtorrent、express 等4款App今日上新
- 【GitHub日报】22-10-10 brew、minio、vite、seaweedfs、dbeaver 等8款App今日上新
- 【GitHub日报】22-10-11 cobra、grafana、vue、ToolJet、redwood 等13款App今日上新
- Photoshop 2018 下载及安装教程(mac+windows全版本都有,包括最新的2023)
- Photoshop 2017 下载及安装教程(mac+windows全版本都有,包括最新的2023)
- Photoshop 2020 下载及安装教程(mac+windows全版本都有,包括最新的2023)
- Photoshop 2023 资源免费下载(mac+windows全版本都有,包括最新的2023)
- 最新版本Photoshop CC2018软件安装教程(mac+windows全版本都有,包括2023