Inconsistent property names implement bean copyProperties

insert image description hereinsert image description here

In this case, is it difficult to copy the bean? If there are N fields with different names, each of them needs to be set, and do you want to smash the keyboard in an instant? Use a tool class to save keyboard money from now on, isn't it incense to flirt with girls?

code above

1. A note

@Inherited
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface CopySourceName {
    
    String value();

}

2. Tools


public class CopyBeanUtils {

    /**
     * ps:Test2 test2 = CopyBeanUtils.springCopyProperties(i1, Test2.class);
     *  spring 的 BeanUtils.copyProperties(source, target) 的封装
     * @param source      原对象
     * @param targetClass 目标对象class
     * @param <T>
     * @return copy完后的对象
     */
    public static <T> T springCopyProperties(Object source, Class<T> targetClass) {
        Assert.notNull(source, "targetClass must not be null");

        T target = BeanUtils.instantiateClass(targetClass);
        BeanUtils.copyProperties(source, target);
        return target;
    }

    /**
     * ps:Test2 test2 = CopyBeanUtils.copyProperties(i1, Test2.class);
     *
     * @param source      原对象
     * @param targetClass 目标对象class
     * @param <T>
     * @return copy完后的对象
     */
    public static <T> T copyProperties(Object source, Class<T> targetClass) {
        Assert.notNull(source, "targetClass must not be null");

        T target = BeanUtils.instantiateClass(targetClass);
        copyProperties(source, target);
        return target;
    }

    public static void copyProperties(Object source, Object target) throws BeansException {
        copyProperties(source, target, null, (String[]) null);
    }

    public static void copyProperties(Object source, Object target, Class<?> editable) throws BeansException {
        copyProperties(source, target, editable, (String[]) null);
    }

    /**
     * @param source           原对象
     * @param target           目标对象
     * @param ignoreProperties 排除某些不需要复制的属性
     * @throws BeansException
     */
    public static void copyProperties(Object source, Object target, String... ignoreProperties) throws BeansException {
        copyProperties(source, target, null, ignoreProperties);
    }

    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> copySourceNameMap = new HashMap<>();

        for (Field field : actualEditable.getDeclaredFields()) {
            CopySourceName annotation = field.getAnnotation(CopySourceName.class);
            if (annotation != null) {
                copySourceNameMap.put(field.getName(), annotation.value());
            }
        }

        for (PropertyDescriptor targetPd : targetPds) {
            Method writeMethod = targetPd.getWriteMethod();
            String name = targetPd.getName();
            String sourceName = copySourceNameMap.get(name);
            if (sourceName != null) name = sourceName;
            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);
                        }
                    }
                }
            }
        }
    }

}

3. Test class

@Data
@Accessors(chain = true)
public class Test1 {

    private String str;

    private List<String> userIds;
}


@Data
@Accessors(chain = true)
public class Test2 {

    private String str;

    @CopySourceName("userIds")
    private List<String> userIdList;
}


public class test {

    public static void main(String[] args) {
        Test1 i1 = new Test1().setStr( "11").setUserIds(CollectionUtil.toList("i", "2222", "111"));
        Test2 test2 = CopyBeanUtils.copyProperties(i1, Test2.class);
        System.out.println(JSONUtil.toJsonStr(test2 ));
    }
}

The implementation logic is basically the same, the tool class is compared with Spring's BeanUtils.copyProperties(source, target); , running speed, unit ms

the first time 50 times 5000 times 50000 times 1000000 times 5000000 times
spring 11 51 168 674 8429
Tools 6 71 260 1096 5312
the second time 50 times 5000 times 50000 times 1000000 times 5000000 times
spring 10 65 200 638 7692
Tools 3 49 237 1184 4359
the third time 50 times 5000 times 50000 times 1000000 times 5000000 times
spring 14 86 211 685 8100
Tools 4 80 259 1072 5266
the fourth time 50 times 5000 times 50000 times 1000000 times 5000000 times
spring 27 71 157 715 8242
Tools 4 107 281 1082 3354
the fifth time 50 times 5000 times 50000 times 1000000 times 5000000 times
spring 9 121 168 653 9455
Tools 3 85 232 1059 5726
{{o.name}}
{{m.name}}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324032036&siteId=291194637