拷贝实体的工具类---BeanObjectCopyUtils

举报
小马哥学JAVA 发表于 2023/02/18 17:49:29 2023/02/18
【摘要】 前言:介绍一个实用的bean对象实体类的拷贝工具,主要封装了两个方法进行实体类的字符拷贝处理,单个实体以及实体列表的拷贝操作。第一步:引用的核心类:BeanUtils核心的思想是根据反射进行类中成员变量的赋值操作,本文一共实现了两种方式的实体拷贝方法:第一种:单个实体的拷贝方法第二种:列表类的实体拷贝方法第二步:核心方法的介绍:核心方法一,介绍了实例化的操作:/** @deprecated ...

前言:

介绍一个实用的bean对象实体类的拷贝工具,主要封装了两个方法进行实体类的字符拷贝处理,单个实体以及实体列表的拷贝操作。

第一步:引用的核心类:

image

BeanUtils

核心的思想是根据反射进行类中成员变量的赋值操作,本文一共实现了两种方式的实体拷贝方法:

第一种:单个实体的拷贝方法
第二种:列表类的实体拷贝方法

第二步:核心方法的介绍:

核心方法一,介绍了实例化的操作:

/** @deprecated */

@Deprecated

public static T instantiate(Class 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 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 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 List copyListObjToListObj(Class desClass, List sourceList){

      List desList=new ArrayList();

      if(sourceList!=null){

         for(int i=0; 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 vouchPostRecordBO = BeanObjectCopyUtils.copyListObjToListObj(VoucherPostBaseBo.class, vouchPostRecordVO);

最后总结:

在封装一些工具类的时候,最好是使用一些官方定义的方法进行二次封装处理,这样有以下的好处,第一,可以保证封装方法的稳定性、安全性;第二,封装的方法之后,可以进行一些根据项目的实际情况进行特殊的处理,比如说日志的处理,报警的处理等等

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。