自定义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}
-