分享一个对象复制的工具类

  • 使用cglib的BeanCopier复制对象的工具类。
  • 性能比spring的BeanUtils,Apache common的BeanUtils快很多倍。
  • 注意:
  • 1)BeanCopier只拷贝名称和类型都相同的属性
  • 2)当目标类的setter数目比getter少时,创建BeanCopier会失败而导致拷贝不成功
  • 3)引用类型不会拷贝,直接引用,所以操作源对象的引用类型属性会导致copy的对象的引用类型属性一起变化。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    public class BeanCopyUtils {
    // 使用WeakHashMap缓存,在内存不足时会自动释放
    private final static Map<String,BeanCopier> BEAN_COPIER_MAP = new WeakHashMap<>();
    private final static Map<String,Converter> CONVERTER_MAP = new WeakHashMap<>();
    private static Object lock1 = new Object();
    private static Object lock2 = new Object();
    private BeanCopyUtils(){}
    /**
    * 创建BeanCopier,并缓存
    * @param src
    * @param target
    * @param useConverter
    * @return
    */
    private static BeanCopier getBeanCopier(Object src,Object target,boolean useConverter) {
    String key = generateKey(src,target,useConverter);
    BeanCopier bc = BEAN_COPIER_MAP.get(key);
    if (null == bc) {
    synchronized (lock1) {
    bc = BEAN_COPIER_MAP.get(key);
    if (null == bc) {
    bc = BeanCopier.create(src.getClass(),target.getClass(),useConverter);
    BEAN_COPIER_MAP.put(key,bc);
    System.out.println("Create BeanCopier with key:" + key);
    }
    }
    }
    return bc;
    }
    /**
    * 复制对象属性
    * @param src
    * @param target
    */
    public static void copy(Object src,Object target) {
    BeanCopier bc = getBeanCopier(src, target, false);
    bc.copy(src,target,null);
    }
    /**
    * 使用自定义的属性转换器复制对象属性
    * @param src
    * @param target
    * @param converter
    */
    public static void copy(Object src,Object target,Converter converter) {
    BeanCopier bc = getBeanCopier(src,target,true);
    bc.copy(src,target,converter);
    }
    /**
    * 对象属性复制,只复制fields中指定的属性,每个属性用逗号分隔
    * @param src
    * @param target
    * @param fields
    */
    public static void copyWithFields(Object src,Object target,final String fields) {
    BeanCopier bc = getBeanCopier(src,target,true);
    bc.copy(src, target, newConverter(src,target,fields,true));
    }
    /**
    * 对象属性复制,排除指定属性
    * @param src
    * @param target
    * @param fields
    */
    public static void copyWithoutFields(Object src,Object target,final String fields) {
    BeanCopier bc = getBeanCopier(src,target,true);
    bc.copy(src, target, newConverter(src,target,fields,false));
    }
    /**
    * new属性转换器,
    * @param fields 需要复制或排除的属性
    * @param fieldCopyFlag 属性复制标识 true:表明fields为需要复制的属性;false:表明fields是需要排除复制的属性
    * @return
    */
    private static Converter newConverter(Object src,Object target,final String fields,final boolean fieldCopyFlag) {
    String key = buildConverterkey(src,target,fields,fieldCopyFlag);
    Converter converter = CONVERTER_MAP.get(key);
    if (null == converter) {
    synchronized (lock2) {
    converter = CONVERTER_MAP.get(key);
    if (null == converter) {
    converter = new Converter() {
    @Override
    public Object convert(Object fieldValue, Class fieldType, Object methodName) {
    String field = methodName.toString().substring(3); // 得到属性名,如Name
    field = field.substring(0,1).toLowerCase() + field.substring(1); // 将首字母小写
    if ((fieldCopyFlag && fields.contains(field)) || (!fieldCopyFlag && !fields.contains(field))) {
    return fieldValue;
    }
    return null;
    }
    };
    CONVERTER_MAP.put(key,converter);
    System.out.println("Created Converter with key:" + key);
    }
    }
    }
    return converter;
    }
    private static String generateKey(Object src,Object target,boolean useConverter) {
    return src.getClass().getName() + target.getClass().getName() + String.valueOf(useConverter);
    }
    private static String buildConverterkey(Object src,Object target,String fields,boolean copyFlag) {
    String baseKey = generateKey(src,target,true);
    String key = baseKey + fields + String.valueOf(copyFlag);
    return key;
    }
    }
Donny wechat
欢迎关注我的个人公众号
打赏,是超越赞的一种表达。
Show comments from Gitment