org.springframework.beans.BeanUtils.copyProperties方法的泛型问题。

用该方法复制时,只要属性名一样,属性类一样,就能复制成功,而不管泛型是否相同。比如下面这段代码:

public class Main {
    public static void main(String[] args){
        SourceClass source = new SourceClass();
        source.getCollection.add("aaa");
        TargetClass target = new TargetClass();
        BeanUtils.copyProperties(source, target);
        System.out.println(target.getCollection.size());
    }
}
class SourceClass {
    private Collection<String> collection = new ArrayList<>();

    public Collection<String> getCollection() {
            return collection;
    }

    public void setCollection(Collection<String> collection) {
            this.collection = collection;
    }
}

class TargetClass {
    private Collection<Long> collection = new ArrayList<>();

    public Collection<Long> getCollection() {
        return collection;
    }

    public void setCollection(Collection<Long> collection) {
        this.collection = collection;
    }

}

输出将是1,因为复制成功了。这不是我们想要的结果,因为会导致类型错误。一种办法是通过多传一个String[]参数,忽略掉这个字段。但我想要的是彻底解决问题,所以写了写面的这个方法:

public class BeanUtils {

    public static void copyProperties(Object source, Object target) {
        copyProperties(source, target, null);
    }

    public static void copyProperties(Object source, Object target,
            String[] ignoreProperties) {
        Assert.notNull(source, "Source must not be null");
        Assert.notNull(target, "Target must not be null");
        Class<?> targetClass = target.getClass();
        Field[] targetFields = targetClass.getDeclaredFields();
        List<String> ignoreList = ignoreProperties == null ? null : Arrays
                .asList(ignoreProperties);
        for (Field targetField : targetFields) {
            String targetFieldName = targetField.getName();
            Method writeMethod = getWriteMethod(targetField);
            if (writeMethod == null
                    || (ignoreList != null && ignoreList.contains(targetFieldName))) {
                continue;
            }
            Field sourceField = null;
            try {
                sourceField = source.getClass().getDeclaredField(targetFieldName);
            } catch (NoSuchFieldException | SecurityException e1) {
                continue;
            }
            ParameterizedType sourceGenericType = (ParameterizedType) sourceField
                    .getGenericType();
            ParameterizedType targetGenericType = (ParameterizedType) targetField
                    .getGenericType();
            if (!genericTypeEquals(sourceGenericType, targetGenericType)) {
                continue;
            }
            Method readMethod = getReadMethod(sourceField);
            if (sourceField == null || readMethod == null) {
                continue;
            }
            Object value = null;
            try {
                value = readMethod.invoke(source);
                writeMethod.invoke(target, value);
            } catch (IllegalAccessException | IllegalArgumentException
                    | InvocationTargetException e) {}
        }
    }

    // 判断字段泛型是否相同
    private static boolean genericTypeEquals(ParameterizedType sourceGenericType,
            ParameterizedType targetGenericType) {
        Type[] sourceTypes = sourceGenericType.getActualTypeArguments();
        Type[] targetTypes = targetGenericType.getActualTypeArguments();
        if (sourceTypes == null) {
            if (targetTypes == null) {
                return true;
            } else {
                return false;
            }
        } else {
            if (targetTypes == null) {
                return false;
            } else {
                int lengthS = sourceTypes.length;
                int lengthT = targetTypes.length;
                if (lengthS != lengthT) {
                    return false;
                } else {
                    for (int i = 0; i < lengthS; i++) {
                        if (!sourceTypes[i].equals(targetTypes[i])) {
                            return false;
                        }
                    }
                    return true;
                }
            }
        }
    }

    // 获取get方法或者is方法(boolean)
    private static Method getReadMethod(Field sourceField) {
        Method method = null;
        Class<?> declaringClass = sourceField.getDeclaringClass();
        String fieldName = StringUtils.capitalize(sourceField.getName());
        try {
            method = declaringClass.getMethod("get" + fieldName);
        } catch (NoSuchMethodException | SecurityException e) {}
        try {
            method = declaringClass.getMethod("is" + fieldName);
        } catch (NoSuchMethodException | SecurityException e) {}
        return method;
    }

    // 获取set方法
    private static Method getWriteMethod(Field targetField) {
        Method method = null;
        Class<?> declaringClass = targetField.getDeclaringClass();
        String fieldName = StringUtils.capitalize(targetField.getName());
        try {
            method = declaringClass.getMethod("set" + fieldName, targetField.getType());
        } catch (NoSuchMethodException | SecurityException e) {}
        return method;
    }

}

彻底的解决了问题。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值