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

来源:互联网 发布:sql字段别名 编辑:程序博客网 时间:2024/06/05 10:38

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

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;    }}

彻底的解决了问题。

0 0