自定义BeanUtils中的copyProperties类复制方法

自定义BeanUtils中的copyProperties类复制方法

  • 首先自定义注解

    import java.lang.annotation.*;
    
    /**
     * @author wyp
     */
    @Inherited
    @Target({ElementType.FIELD})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface CopyTargetName {
        String value();
    }
    
  • 自定义类转换工具类

    import cn.xc.annotation.CopyTargetName;
    import org.springframework.beans.BeanUtils;
    import org.springframework.beans.BeansException;
    import org.springframework.beans.FatalBeanException;
    import org.springframework.lang.Nullable;
    import org.springframework.util.Assert;
    import org.springframework.util.ClassUtils;
    
    import java.beans.PropertyDescriptor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.List;
    
    /**
     * @author wyp
     */
    public class BeanConvertUtils {
    
        /**
         * 类转换 A->B
         * @param object A对象
         * @param targetType B.class
         * @param <T> A
         * @param <V> B
         * @return B对象或者null
         */
        public static  <T, V> V convert(T object, Class<V> targetType) {
            if (object != null && targetType != null) {
                V result = BeanUtils.instantiateClass(targetType);
                BeanUtils.copyProperties(object, result);
                return result;
            } else {
                return null;
            }
        }
    
        /**
         * 自定义类转换 A->B
         * 在B对象属性上加 @CopyTargetName("自定义属性名") 来复制两类不同的属性
         * @param object A对象
         * @param targetType B.class
         * @param <T> A
         * @param <V> B
         * @return B对象或者null
         */
        public static  <T, V> V customizeConvert(T object, Class<V> targetType) {
            if (object != null && targetType != null) {
                V result = BeanUtils.instantiateClass(targetType);
                copyProperties(object, result);
                return result;
            } else {
                return null;
            }
        }
    
        /**
         * 集合形式的类转换 List<A>->List<B>
         * @param objectList A对象集合
         * @param targetType B.class
         * @param <T> A
         * @param <V> B
         * @return B对象集合或者null
         */
        public static  <T, V> List<V> convertList(List<T> objectList, Class<V> targetType) {
            List<V> resultList = null;
            if (objectList != null) {
                resultList = new ArrayList<V>();
    
                for (T object : objectList) {
                    resultList.add(convert(object, targetType));
                }
            }
            return resultList;
        }
    
        /**
         * 自定义集合形式的类转换 List<A>->List<B>
         * 在B对象属性上加 @CopyTargetName("自定义属性名") 来复制两类不同的属性
         * @param objectList A对象集合
         * @param targetType B.class
         * @param <T> A
         * @param <V> B
         * @return B对象集合或者null
         */
        public static  <T, V> List<V> customizeConvertList(List<T> objectList, Class<V> targetType) {
            List<V> resultList = null;
            if (objectList != null) {
                resultList = new ArrayList<V>();
    
                for (T object : objectList) {
                    resultList.add(customizeConvert(object, targetType));
                }
            }
            return resultList;
        }
    
        public static void copyProperties(Object source, Object target) throws BeansException {
            copyProperties(source, target, 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 = BeanUtils.getPropertyDescriptors(actualEditable);
            List<String> ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null);
    
            HashMap<String, String> copyTargetNameMap = new HashMap<>();
    
            for (Field field : actualEditable.getDeclaredFields()) {
                CopyTargetName annotation = field.getAnnotation(CopyTargetName.class);
                if (annotation != null){
                    copyTargetNameMap.put(field.getName(), annotation.value());
                }
            }
    
            for (PropertyDescriptor targetPd : targetPds) {
                Method writeMethod = targetPd.getWriteMethod();
                String name = targetPd.getName();
                String targetName = copyTargetNameMap.get(name);
                if (targetName != null){
                    name = targetName;
                }
                if (writeMethod != null && (ignoreList == null || !ignoreList.contains(name))) {
                    PropertyDescriptor sourcePd = BeanUtils.getPropertyDescriptor(source.getClass(), name);
                    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 ex) {
                                throw new FatalBeanException(
                                        "Could not copy property '" + name + "' from source to target", ex);
                            }
                        }
                    }
                }
            }
        }
    }
    
  • 测试

    • 定义两个有不同属性的类

      A.java

      public class A{
          private String name;
          private String desc;
          private Integer age;
      
          public A() {
          }
      
          public A(String name, String desc, Integer age) {
              this.name = name;
              this.desc = desc;
              this.age = age;
          }
      //getter setter toString 省略...
      }
      

      B.java

      public class B{
          private String name;
          @CopyTargetName("desc")
          private String remark;
          private Integer age;
      
          public B() {
          }
      
          public B(String name, String remark, Integer age) {
              this.name = name;
              this.remark = remark;
              this.age = age;
          }
      //getter setter toString 省略...
      }
      
    • 测试

      A a = new A("wyp","hello",20);
      B b1 = covert(a,B.class);
      System.out.println("原生:" + b1);
      B b2 = customizeConvert(a,B.class);
      System.out.println("自定义:" + b2);
      
    • 测试结果

      原生:B{name='wyp', remark='null', age=20}
      自定义:B{name='wyp', remark='hello', age=20}
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小辰~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值