All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.foreveross.springboot.dubbo.utils.BeanHelper Maven / Gradle / Ivy

There is a newer version: 2.3.8
Show newest version
package com.foreveross.springboot.dubbo.utils;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

/**
 * Created by VectorHo on 16/2/23.
 *
 * Bean工具类: 深度克隆 etc.
 *
 */
public class BeanHelper {

    protected static Logger logger = LoggerFactory.getLogger(BeanHelper.class);

    private static final String DATE_DEFAULT_PATTERN = "yyyy-MM-dd HH:mm:ss";
    private static final String[] DATE_PARSE_PATTERNS = new String[]{"yyyy-MM-dd", DATE_DEFAULT_PATTERN, "yyyy-MM-dd HH:mm"};

    private BeanHelper() {
    }

    private static Map origFieldMap = new HashMap();
    private static Map destFieldMap = new HashMap();


    private static class BeanField {
        private String name;
        private Object value;
        private Class clazz;

        private Field field = null;
        private Object instance = null;

        private BeanField() {}

        static BeanField getBeanField(Field field, Object instance, boolean withValue) {
            if ((field.getModifiers() & Modifier.STATIC) != 0) {
                return null;
            }
            BeanField bf = new BeanField();
            {
                bf.name = field.getName();
                bf.clazz = field.getType();
                if (withValue) { // 带上值
                    try {
                        if (field.isAccessible()) {
                            bf.value = field.get(instance);
                        } else {
                            field.setAccessible(true);
                            bf.value = field.get(instance);
                            field.setAccessible(false);
                        }
                    } catch (Exception e) {
                        logger.error("BeanHelper.getBeanField exception: ", e);
                    }
                }
                bf.field = field;
                bf.instance = instance;
            }
            return bf;
        }

        static BeanField getBeanField(String name, Map instance) {
            BeanField bf = new BeanField();
            {
                bf.name = name;
                try {
                    bf.value = instance.get(name);
                    if (bf.value == null) {
                        bf.clazz = Object.class;
                    } else {
                        bf.clazz = bf.value.getClass();
                    }
                } catch (Exception e) {
                    logger.error("BeanHelper.getBeanField exception: ", e);
                }
                bf.field = null;
                bf.instance = instance;
            }
            return bf;
        }

        static BeanField copyBeanField(BeanField field, Map instance) {
            BeanField bf = new BeanField();
            {
                bf.name = field.name;
                bf.clazz = field.getClazz();
                bf.field = null;
                bf.instance = instance;
            }
            return bf;
        }

        public  T getValue() {
            return (T) value;
        }

        public void setValue(Object value) {
            if (field != null && instance != null) {
                try {
                    if (field.isAccessible()) {
                        field.set(instance, value);
                    } else {
                        field.setAccessible(true);
                        field.set(instance, value);
                        field.setAccessible(false);
                    }
                } catch (Exception e) {
                    logger.error("Can't setting the value: " + field + ", value=" + value);
                }
            } else {
                ((Map) instance).put(name, value);
            }
            this.value = value;
        }

        public String getName() {
            return name;
        }

        public Class getClazz() {
            return clazz;
        }

        public String toString() {
            return "BeanField [clazz=" + clazz + ", field=" + field
                    + ", instance=" + instance + ", name=" + name + ", value="
                    + value + "]";
        }
    }

    // 对象克隆, 非覆盖dest成员变量 -> PUT
    public static  T mapPartOverrider(Object dest, Object orig) {
        return BeanHelper.copyProperties(dest, orig, true);
    }

    // 对象克隆, 覆盖dest成员变量 -> POST GET
    public static  T mapCompleteOverrider(Object dest, Object orig) {
        return BeanHelper.copyProperties(dest, orig, false);
    }


    public static  T copyProperties(Object dest, Object orig) {
        return BeanHelper.copyProperties(dest, orig, false);
    }

    // 对象深度克隆
    private static  T copyProperties(Object dest, Object orig, boolean no_overrider) {
        if (orig == null || dest == null) {
            return (T) dest;
        }
        BeanHelper.origFieldMap.clear();
        BeanHelper.destFieldMap.clear();

        if (orig instanceof Map) {// Is Map and Not cache
            Map origMap = (Map) orig;
            for (Entry entry : (Set) origMap.entrySet()) {
                String name = entry.getKey().toString();
                BeanField beanField = BeanField.getBeanField(name, origMap);
                if (beanField != null) {
                    origFieldMap.put(name, beanField);
                }
            }
        } else {// Is Object
            Class clazz = orig.getClass();
            while (clazz != null && clazz != Object.class) {
                Field[] origFields = clazz.getDeclaredFields();
                for (Field f : origFields) {
                    BeanField beanField = BeanField.getBeanField(f, orig, true);
                    if (beanField != null && !origFieldMap.containsKey(f.getName())) {
                        origFieldMap.put(f.getName(), beanField);
                    }
                }
                clazz = clazz.getSuperclass();
            }
        }

        if (dest instanceof Map) {// Is Map and Not cache
            for (Entry entry : origFieldMap.entrySet()) {
                BeanField beanField = BeanField.copyBeanField(entry.getValue(), (Map) dest);
                if (beanField != null) {
                    destFieldMap.put(entry.getKey(), beanField);
                }
            }
        } else {// Is Object
            Class clazz = dest.getClass();
            while (clazz != null && clazz != Object.class) {
                Field[] destFields = clazz.getDeclaredFields();
                for (Field f : destFields) {
                    BeanField beanField = BeanField.getBeanField(f, dest, no_overrider); // orig -> dest 成员变量非覆盖式
                    if (beanField != null && !destFieldMap.containsKey(f.getName())) {
                        destFieldMap.put(f.getName(), beanField);
                    }
                }
                clazz = clazz.getSuperclass();
            }
        }

        // 克隆赋值
        for (Entry entry : origFieldMap.entrySet()) {
            BeanField origField = entry.getValue();
            BeanField destField = destFieldMap.get(entry.getKey());
            // 检查类型
            if (destField == null || origField == null) {
                continue;
            }
            if (!(origField.getClazz() instanceof Class && destField.getClazz() instanceof Class)) {
                continue;
            }
            if (!no_overrider && origField.getClazz() == destField.getClazz()) {
                destField.setValue(origField.getValue());
            } else if(origField.getClazz() == destField.getClazz()){
                Class destClazz = (Class) destField.getClazz();
                Class origClazz = (Class) origField.getClazz();

                if ((destClazz.isPrimitive() || Number.class.isAssignableFrom(destClazz)) && (origClazz.isPrimitive()
                        || Number.class.isAssignableFrom(origClazz)
                        || CharSequence.class.isAssignableFrom(origClazz))) { // primitive type

                    boolean isString = CharSequence.class.isAssignableFrom(origClazz);
                    Object value = origField.getValue();

                    if(destField.getValue() != null && no_overrider && value == null) {
                        logger.debug("不覆盖此属性. {}", destField.getName());
                    } else {
                        if (value == null) { /* if orig value is null */
                            if (destClazz.isPrimitive()) {
                                destField.setValue((byte) 0);
                            } else {
                                destField.setValue(null);
                            }
                        } else { /* if orig value is not null */
                            if (destClazz == Double.class || destClazz == double.class) {
                                if (isString) {
                                    destField.setValue(new Double(String.valueOf(value)));
                                } else {
                                    destField.setValue(((Number) value).doubleValue());
                                }
                            } else if (destClazz == Float.class || destClazz == float.class) {
                                if (isString) {
                                    destField.setValue(new Float(String.valueOf(value)));
                                } else {
                                    destField.setValue(((Number) value).floatValue());
                                }
                            } else if (destClazz == Long.class || destClazz == long.class) {
                                if (isString) {
                                    destField.setValue(new Long(String.valueOf(value)));
                                } else {
                                    destField.setValue(((Number) value).longValue());
                                }
                            } else if (destClazz == Integer.class || destClazz == int.class) {
                                if (isString) {
                                    destField.setValue(new Integer(String.valueOf(value)));
                                } else {
                                    destField.setValue(((Number) value).intValue());
                                }
                            } else if (destClazz == Short.class || destClazz == short.class) {
                                if (isString) {
                                    destField.setValue(new Short(String.valueOf(value)));
                                } else {
                                    destField.setValue(((Number) value).shortValue());
                                }
                            } else if (destClazz == Byte.class || destClazz == byte.class) {
                                if (isString) {
                                    destField.setValue(new Byte(String.valueOf(value)));
                                } else {
                                    destField.setValue(((Number) value).byteValue());
                                }
                            } else if (destClazz == BigDecimal.class && (origClazz == Double.class
                                    || origClazz == double.class || origClazz == Float.class
                                    || origClazz == float.class || isString)) {
                                if (isString) {
                                    destField.setValue(BigDecimal.valueOf(new Double(String.valueOf(value))));
                                } else {
                                    destField.setValue(BigDecimal.valueOf(((Number) value).doubleValue()));
                                }

                            } else if (destClazz == BigDecimal.class) {
                                if (isString) {
                                    destField.setValue(BigDecimal.valueOf(new Double(String.valueOf(value))));
                                } else {
                                    destField.setValue(BigDecimal.valueOf(((Number) value).longValue()));
                                }
                            } else {
                                logger.debug(destField + " Can't set Unknowed Number value!");
                            }
                        } /* END if value is not null */
                    }
                } else if (destClazz == boolean.class || destClazz == Boolean.class) { // Object to Boolean
                    Object value = origField.getValue();
                    if(destField.getValue() != null && no_overrider && value == null) {
                        logger.debug("不覆盖此属性. {}", destField.getName());
                    } else {
                        if (origClazz == boolean.class || origClazz == Boolean.class) {
                            destField.setValue(value);
                        } else {
                            destField.setValue(Boolean.valueOf(String.valueOf(value)));
                        }
                    }
                } else if (Date.class.isAssignableFrom(destClazz) && Date.class.isAssignableFrom(origClazz)) { // Date to Date
                    Date value = origField.getValue();
                    if(destField.getValue() != null && no_overrider && value == null) {
                        logger.debug("不覆盖此属性. {}", destField.getName());
                    } else {
                        if (java.sql.Date.class == destClazz) {
                            destField.setValue(value == null ? null : new java.sql.Date(value.getTime()));
                        } else {
                            destField.setValue(value == null ? null : value);
                        }
                    }
                } else if (Date.class.isAssignableFrom(destClazz) && CharSequence.class.isAssignableFrom(origClazz)) { // String to Date
                    CharSequence value = origField.getValue();
                    if(destField.getValue() != null && no_overrider && value == null) {
                        logger.debug("不覆盖此属性. {}", destField.getName());
                    } else {
                        Date parseDate = null;
                        try {
                            parseDate = DateUtils.parseDate(value.toString(), DATE_PARSE_PATTERNS);
                        } catch (Exception e) {
                            logger.error(e.getMessage());
                        }
                        if (value == null) {
                            destField.setValue(null);
                        } else if (java.sql.Date.class == destClazz) {
                            destField.setValue(new java.sql.Date(parseDate.getTime()));
                        } else {
                            destField.setValue(parseDate);
                        }
                    }
                } else if (String.class.isAssignableFrom(destClazz) && Date.class.isAssignableFrom(origClazz)) { // Date to String
                    Date value = origField.getValue();
                    // 非覆盖模式: 目标有值且非覆盖式true的情况
                    destField.setValue(destField.getValue() != null && no_overrider && value == null ? String.valueOf(destField.getValue()) : DateFormatUtils.format(value, DATE_DEFAULT_PATTERN));
                } else if (String.class.isAssignableFrom(destClazz)) { // Object to String
                    Object value = (Object) origField.getValue();
                    // 非覆盖模式: 目标有值且非覆盖式true的情况
//                    destField.setValue(destField.getValue() != null && no_overrider && value == null ? String.valueOf(destField.getValue()) : String.valueOf(value));
                    if(destField.getValue() != null){//destValue!=null
                        destField.setValue( no_overrider && value == null ? String.valueOf(destField.getValue()) :(value==null?null: String.valueOf(value)));
                    }else{
                        destField.setValue( no_overrider && value == null ? null :(value==null?null: String.valueOf(value)));
                    }
                    // Custom complex type
                } else if ((destClazz.getName().indexOf("java.") > -1 || destClazz.getName().indexOf("javax.") > -1) && (origClazz.getName().indexOf("java.") > -1 || origClazz.getName().indexOf("javax.") > -1)) {
                    logger.debug("Not support the complex type:" + destField + ", " + origField);
                } else {
                    logger.debug("Type is not match: " + destField + ", " + origField);
                }
            } /* END origField.getClazz() != destField.getClazz() */
        }
        return (T) dest;
    }





//    public static void main(String[] args) {
//        B b = new B();
//        b.print();
//
//        C c = new C();
//
////        Map map = new HashMap();{
////            map.put("aa", "aa");
////            map.put("b", "b");
////            map.put("c", 11L);
////            map.put("d", 11);
////            map.put("e", new Date());
////            map.put("f", "11");
////            map.put("g", 111.1D);
////            map.put("h", "2013-01-01");
////            map.put("i", new Date());
////            map.put("j", 111L);
////            map.put("k", new java.sql.Date(new Date().getTime()));
////        }
////        {
////            long start = System.currentTimeMillis();
////            for (int i = 0; i < 10000; i++) {
////                BeanHelper.copyProperties(c, b, true);
////            }
////            logger.debug("Object2Object:" + (System.currentTimeMillis() - start) / 10000.0);
////        }
////        {
////            long start = System.currentTimeMillis();
////            for (int i = 0; i < 10000; i++) {
////                BeanHelper.copyProperties(c, map, false);
////            }
////            logger.debug("Map2Object:" + (System.currentTimeMillis() - start) / 10000.0);
////        }
////        {
////            long start = System.currentTimeMillis();
////            for (int i = 0; i < 10000; i++) {
////                BeanHelper.copyProperties(new HashMap(), b, false);
////            }
////            logger.debug("Object2Map:" + (System.currentTimeMillis() - start) / 10000.0);
////        }
////        {
////            long start = System.currentTimeMillis();
////            for (int i = 0; i < 10000; i++) {
////                BeanHelper.copyProperties(new HashMap(), map, false);
////            }
////            logger.debug("Map2Map:" + (System.currentTimeMillis() - start) / 10000.0);
////        }
//        c = BeanHelper.copyProperties(c, b);
//        System.out.println(c);
////        System.out.println(c = BeanHelper.copyProperties(c, b, false));
////        System.out.println(BeanHelper.copyProperties(c, map, false));
////        System.out.println(BeanHelper.copyProperties(new HashMap(), b, false));
////        System.out.println(BeanHelper.copyProperties(new HashMap(), map, false));
//    }

    private static class A {
        private int a = 1; // 继承的成员变量

        void print() {
            System.out.println(getClass());
        }
    }


    private static class B extends A {
        private String b;
        private String c = null;
        private Long d = 10l;
        private int e = 0;
        private Date f = new Date();
        private Double g = 111.2D;
        private String h = "2015-01-02";
        private Date i = new Date();
        private Long j = 112L;
        // String to Number
        private String k = "kkkk";
        // Other
        private Long l = 112L;
        private java.sql.Date m = new java.sql.Date(new Date().getTime());

//        private static String aa = "aa";
//
//        //Same Type
//        private String b = "b";
//        private Long c;
//        private int d;
//        private Date e = new Date();
//        //String to Number
//        private String f;
//        //Number to String
//        private Double g = 111.1D;
//        //String to Date
//        private String h = "2015-01-01";
//        //Date to String
//        private Date i = new Date();
//        //Other
//        private Long j = 111L;
//        private java.sql.Date k = new java.sql.Date(new Date().getTime());
    }

    private static class C {
        private int a = 10;

        private String b = "bb";
        private String c = "cc";

        private Long d;
        private int e = 50;
        private Date f = new Date();
        private Double g = 111.1D;
        private String h = "2015-01-01";
        private Date i = new Date();
        private Long j = 111L;
        // String to Number
        private String k;
        // Other
        private Long l = 111L;
        private java.sql.Date m = new java.sql.Date(new Date().getTime());

//        private static String aa = "cc";
//        private static String bb = "bb";
//
//        //Same Type
//        private String b = "b";
//        private Long c = 11L;
//        private int d = 11;
//        private Date e = new Date();
//        //String to Number
//        private String f = "11";
//        //Number to String
//        private Double g = 111.1D;
//        //String to Date
//        private String h = "2013-01-01";
//        //Date to String
//        private Date i = new Date();
//        //Other
//        private Long j = 111L;
//        private java.sql.Date k = new java.sql.Date(new Date().getTime());
////
//        private int a;
//        //Same Type
//        private String b;
//        private Long c;
//        private int d;
//        private Date e;
//        //String to Number
//        private long f;
//        //Number to String
//        private String g;
//        //String to Date
//        private Date h;
//        //Date to String
//        private String i;
//        //Other
//        private Integer j;
//        private Date k;

        @Override
        public String toString() {
            return "C.class [a= " + a + ", b=" + b + ", c=" + c + ", d=" + d + ", e="
                    + e + ", f=" + f + ", g=" + g + ", h=" + h + ", i=" + i
                    + ", j=" + j + ", k=" + k + ", l=" + l + ", m=" + m + "]";
        }

    }
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy