实体类复制某一部分属性值,避免set/get

有时候不想复制整个类的所有属性,只需要一部分属性,为了避免大量get/set,采用反射方式做复制处理.

1.方法类: CopyBeanValueUtil

/**
 * @author wangfuxu
 * @date: 2021/11/19
 * @description: 使用前提:两个类属性字段一样,不一样需要自己添加适配器
 * 在复制某两个类某些属性时,可使用此方法,前提两个类有相同字段属性名
 * 只需要在目标类和字段上加注@CopyValue注解
 * 两种:
 * 类上默认CONTAIN,字段必须标注了才复制
 * 类上标注EXCLUDE,字段标注EXCLUDE的不复制,剩下全部复制
 * 调用copyValue方法即可
 * //todo 采用适配器+责任链模式
 */
@Slf4j
public class CopyBeanValueUtil {


    private static CopyBeanValue copyBeanValue = new CopyBeanValue();

    /**
     * 复制字段值
     *
     * @param source   源字段
     * @param supplier 目标字段
     * @return 目标类
     */
    public static <Source, Target> Target copyValue(Source source, Supplier<Target> supplier) {
        return (Target) copyBeanValue.copyValue(source, supplier);
    }

    /**
     * 复制字段值
     *
     * @param source 源字段
     * @param target 目标字段
     * @return
     */
    public static <Source, Target> void copyValue(Source source, Target target) {
        copyBeanValue.copyValue(source, target);
    }


    private static class CopyBeanValue<Source, Target> {
        /**
         * 获得所有字段数组
         *
         * @param t
         * @return 字段数组
         */
        public Field[] getSourceFields(@NotNull Source t) {
            Class clazz = t.getClass();
            if (clazz == null) {
                return null;
            }
            Field[] declaredFields = clazz.getDeclaredFields();
            return declaredFields;
        }

        /**
         * 获得所有字段数组Map
         *
         * @param t
         * @return 字段数组
         */
        public Map<String, Field> getTargetFields(@NotNull Target t) {
            Class clazz = t.getClass();
            if (clazz == null) {
                return null;
            }
            Field[] declaredFields = clazz.getDeclaredFields();
            Map<String, Field> map = MapUtil.createMap(HashMap.class);
            for (Field field : declaredFields) {
                map.put(field.getName(), field);
            }
            return map;
        }


        public Target copyValue(@NotNull Source source, @NotNull Supplier<Target> supplier) {
            Target target = supplier.get();
            copyValue(source, target);
            return target;
        }


        public void copyValue(@NotNull Source source, @NotNull Target target) {
            try {
                CopyValue clazzCopyValue = target.getClass().getAnnotation(CopyValue.class);
                Field[] fields = getSourceFields(source);
                Map<String, Field> targetFields = getTargetFields(target);
                for (Field sourceField : fields) {
                    sourceField.setAccessible(true);
                    if (null != sourceField.get(source) && targetFields.containsKey(sourceField.getName())) {
                        CopyValue copyValue = targetFields.get(sourceField.getName()).getAnnotation(CopyValue.class);
                        //(类为准)类标注为包含 & 字段添加标注
                        Boolean conditionOne = CONTAIN.equals(clazzCopyValue.type()) && null != copyValue;
                        // 类标注为排除 & 字段添加标注
                        Boolean conditionTwo = EXCLUDE.equals(clazzCopyValue.type()) && (copyValue == null || !EXCLUDE.equals(copyValue.type()));
                        if (conditionOne || conditionTwo) {
                            Field targetField = targetFields.get(sourceField.getName());
                            setTargetValue(targetField, sourceField, target, source);
                        }
                    }
                }

            } catch (Exception e) {
                log.error("CopyBeanValueUtil#copyValue have error:", e);
            }
        }

        /**
         * 简单转换器
         *
         * @param targetField
         * @param sourceField
         */
        private void setTargetValue(Field targetField, Field sourceField, Target target, Source source) throws IllegalAccessException {
            Type targetFiledType = targetField.getGenericType();
            if (targetFiledType.getTypeName().equals(sourceField.getGenericType().getTypeName())) {
                targetField.setAccessible(true);
                targetField.set(target, sourceField.get(source));
            } else {
                if (targetFiledType.getTypeName().toUpperCase().equals(DataType.STRING) && sourceField.getGenericType().getTypeName().toUpperCase().equals(DataType.DATE)) {
                    Date value = (Date) sourceField.get(source);
                    String stringValue = DateUtil.format(value, "yyyy-MM-dd HH:mm:ss");
                    setValue(targetField, target, stringValue);
                } else if (targetFiledType.getTypeName().toUpperCase().equals(DataType.LONG) && sourceField.getGenericType().getTypeName().toUpperCase().equals(DataType.DOUBLE)) {
                    Long value = ((Double) sourceField.get(source)).longValue();
                    setValue(targetField, target, value);
                } else if (targetFiledType.getTypeName().toUpperCase().equals(DataType.DOUBLE) && sourceField.getGenericType().getTypeName().toUpperCase().equals(DataType.LONG)) {
                    Double value = ((Long) sourceField.get(source)).doubleValue();
                    setValue(targetField, target, value);
                } else if (targetFiledType.getTypeName().toUpperCase().equals(DataType.DATE) && sourceField.getGenericType().getTypeName().toUpperCase().equals(DataType.STRING)) {
                    String value = String.valueOf(sourceField.get(source));
                    Date date = DateUtil.parse(value, "yyyy-MM-dd HH:mm:ss");
                    setValue(targetField, target, date);
                }
            }
        }

        private <T> void setValue(Field targetField, Target target, T value) throws IllegalAccessException {
            targetField.setAccessible(true);
            targetField.set(target, value);
        }

    }

}

2.注解类

/**
 * @author wangfuxu
 * 标记需要被copy的属性或类
 * EXCLUDE:排除
 * CONTAIN:包含
 * 默认扫描包含注解的属性
 */
@Target(value = {ElementType.FIELD, ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
@Documented
public @interface CopyValue {
    CopyValueType type() default CopyValueType.CONTAIN;
}

3.枚举类

/**
 * @author wangfuxu
 * 标记需要被copy的属性或类
 * EXCLUDE:排除
 * CONTAIN:包含
 * 默认扫描包含注解的属性
 */
@Target(value = {ElementType.FIELD, ElementType.TYPE})
@Retention(value = RetentionPolicy.RUNTIME)
@Documented
public @interface CopyValue {
    CopyValueType type() default CopyValueType.CONTAIN;
}

4.转换器属性类

/**
 * @author wangfuxu
 */
public interface DataType {
    String STRING = "JAVA.LANG.STRING";
    String INTEGER = "JAVA.LANG.INTEGER";
    String LONG = "JAVA.LANG.LONG";
    String DOUBLE = "JAVA.LANG.DOUBLE";
    String SHORT = "JAVA.LANG.SHORT";
    String DATE = "JAVA.UTIL.DATE";
    String CHAR = "JAVA.LANG.CHAR";

}

备注:此方法采用反射模式,对于JavaBean应该采用自省模式比较好,时间有限,仅做备注.后期有时间补充

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值