zoukankan      html  css  js  c++  java
  • Java对象属性复制备忘

    基于面向对象和各种设计要求,一个分层的Java系统中存在各种 VO、DTO、BO、PO 之类的对象,同一个实体的不同对象需要大量的属性复制,为了避免手动操作,需要一种便捷对象浅复制工具类,下面是各个常见工具对比。

    列举

    //cglib
    net.sf.cglib.beans.BeanCopier.create 
    net.sf.cglib.beans.BeanCopier.copy
    
    //spring-beans
    org.springframework.beans.BeanUtils.copyProperties
    
    //commons-beanutils
    org.apache.commons.beanutils.BeanUtils.copyProperties
    org.apache.commons.beanutils.PropertyUtils.copyProperties
    

    原理

    以上4种方式都是通过自动调用原对象的getter方法,再用目标对象的setter方法设置进去,区别在于BeanCopier先通过create创建了一个以BeanCopier派生的动态代理类,其创建的copy方法实现包含以上所有getter和setter的调用过程,调用copy可以达到原生代码方式的性能;而其他所有方式如spring-beans和commons-beanutils的实现都是通过反射逐个调用getter和setter,性能相比前者较差。

    细节

    细节 Apache-PropertyUtils Apache-BeanUtils Spring-BeanUtils Cglib-BeanCopier
    相同属性名,不同类型转换Converter扩展 NO Yes Yes Yes,较难用,需要对每一种属性类型都做转换
    相同属性名,Integer和int的处理 OK OK OK 不拷贝,忽略该属性
    相同属性名,Long和Integer的处理 异常报错 OK,自动互转 不拷贝,忽略该属性 不拷贝,忽略该属性
    对基本类型null值处理(Integer,Long等) OK 特殊,会将null转为0,用Converter后解决 OK OK
    对source特殊属性的限制:(Date,BigDecimal等) OK NO,异常出错,必须用Converter才行 OK OK
    Get和set方法不匹配的处理 OK,忽略该属性 OK,忽略该属性 OK,忽略该属性 创建异常(仅限source有get方法在target中找不到对应set方法)
    调用异常处理 需处理异常 需处理异常 RuntimeException RuntimeException

    需要兼容性的场景,优先spring-beans提供的BeanUtils,功能强大,兼容性最好。需要性能的场景,优先选择cglib提供的BeanCopier,性能最好(注意需要缓存create结果)。

    还有一项需要注意的是所有拷贝都是浅拷贝,注意属性引用不变,避免新老对象同时读写引起问题,这需要通过场景约束。

    结论

    事实上,由于不同工具类实现不同,细节差异非常多,一个团队最好通过规范统一使用某一个,并对其熟悉和理解,不必追求万能的工具类。我在新项目中选择了BeanCopier,并通过场景和限制约定避免踩坑。

    • 场景约束:主要用于同模型的DO、DTO和VO等之间转换。
    • 限制约定:要求两者同名属性具有严格相同类型,且其getter和setter一一对应,不能包含特殊逻辑。
  • 相关阅读:
    poj 2528 Mayor's posters (线段树+离散化)
    poj 1201 Intervals (差分约束)
    hdu 4109 Instrction Arrangement (差分约束)
    poj 1195 Mobile phones (二维 树状数组)
    poj 2983 Is the Information Reliable? (差分约束)
    树状数组 讲解
    poj 2828 Buy Tickets (线段树)
    hdu 1166 敌兵布阵 (树状数组)
    Ubuntu网络配置
    Button控制窗体变量(开关控制灯的状态)
  • 原文地址:https://www.cnblogs.com/pyx0/p/copy-properties.html
Copyright © 2011-2022 走看看