java bean属性拷贝工具类比对(性能+功能)

业务系统中经常需要两个对象进行属性的拷贝,不能否认逐个的对象拷贝是最快速最安全的做法,但是当数据对象的属性字段数量超过程序员的容忍的程度比如通常超过5个属性的时候,代码因此变得臃肿不堪,使用一些方便的对象拷贝工具类将是很好的选择。

目前流行的较为公用认可的工具类:

Apache的两个版本:(反射机制)

org.apache.commons.beanutils.PropertyUtils.copyProperties(Object dest, Object orig)

org.apache.commons.beanutils.BeanUtils.copyProperties(Object dest, Object orig)

Spring版本:(反射机制)

org.springframework.beans.BeanUtils.copyProperties(Object source, Object target, Class editable, String[] ignoreProperties)

新版本的spring也集成了cglib版:org.springframework.cglib.beans.BeanCopier

cglib版本:(使用动态代理,效率高)

net.sf.cglib.beans.BeanCopier.copy(Object paramObject1, Object paramObject2, Converter paramConverter)

dozer版本(xml配置映射,性能最低下):

org.dozer.DozerBeanMapper.map(Object source, Class<T> destinationClass)

就API而言,使用哪个工具类无所谓,我们通常关心两点,功能完善性以及性能。

性能测试:

// 源POJO
package tf56.lf.lfbase.model.dto;

import java.io.Serializable;

import tf56.lf.lfbase.model.domain.LfProduct;

/**
 * ClassName:ProductDTO
 *
 * @version  1.0
 * @since    v1.0
 * @Date     2017年6月19日    yuebiao.wu
 */

public class ProductDTO extends LfProduct implements Serializable{

    private static final long serialVersionUID = -1296801547926874402L;

}

// 目标POJO
package tf56.lf.lfbase.model.domain;

import java.io.Serializable;
import java.util.Date;

import lombok.Getter;
import lombok.Setter;

/**
 * ClassName:Product
 *
 * @author tool
 * @version 1.0
 * @since v1.0
 * Date Jun 26, 2017 2:40:42 PM
 */
@Getter
@Setter
public class LfProduct implements Serializable {

    private static final long serialVersionUID = 4054863309367744108L; 

    /* 产品id */
    private String lfProductId;
    /* 物流金融账号 */
    private String lfAccountId;
    /* 产品名称 */
    private String productName;
    /* 产品类型(BAOFU:保付; MIAOFU:秒付; JISHIFU:即时付;) */
    private String productType;
    /* 适用场景列表(逗号分隔)(COD:代收货款; FREIGHT:运费;) */
    private String sceneTypes;
    /* 产品描述 */
    private String productDescription;
    /* 产品规则描述 */
    private String productRoleDescription;
    /* 放款触发行为 */
    private String loanAction;
    /* 收款触发行为 */
    private String repayAction;
    /* 产品状态(ENABLE:启用; DISABLE:停用;) */
    private String productStatus;
    /* 预警阀值 */
    private Long warnBalance;
    /* 发货人是否控制额度(1:是; 0:否;) */
    private Integer isConsignerCreditLimit;
    /* 承运商是否控制额度(1:是; 0:否;) */
    private Integer isExpressCreditLimit;

    private String    productAgreementUrl;

    private String    poundageCalcType;

    private String    poundageRate;

    /* 备注1 */
    private String remark1;
    /* 操作员编号 */
    private String operatorId;
    /* 输入日期 */
    private Date inputDate;
    /* 记录更新时间 */
    private Date stampDate;

}

BeanCopier

        Mapper wrapper = new DozerBeanMapper();
        ProductDTO pdt = new ProductDTO();
        pdt.setIsConsignerCreditLimit(3);
        pdt.setLoanAction("323f3");
        pdt.setProductName("feiwefe");
        pdt.setPoundageRate("f332r3");
        long beg = System.currentTimeMillis();
        PropertyUtilsBean bean = new PropertyUtilsBean();

        BeanCopier copier = BeanCopier.create(ProductDTO.class, LfProduct.class, false);
        for (int i=0;i<1000;i++) {
            LfProduct lfPdt = new LfProduct();
//            try {
//                try {
//                    bean.copyProperties(lfPdt, pdt);
//                } catch (IllegalAccessException | InvocationTargetException e) {
//                    // TODO Auto-generated catch block
//                    e.printStackTrace();
//                }
//            } catch (NoSuchMethodException e) {
//                // TODO Auto-generated catch block
//                e.printStackTrace();
//            }
            copier.copy(pdt, lfPdt, null);
            if (i==3) {
//                System.out.println(JacksonHelper.toJSON(lfPdt));
            }
//            lfPdt = wrapper.map(pdt, LfProduct.class);
            lfPdt.setInputDate(new Date());
        }
        System.out.println(System.currentTimeMillis() - beg);

大约140ms左右。

        Mapper wrapper = new DozerBeanMapper();
        ProductDTO pdt = new ProductDTO();
        pdt.setIsConsignerCreditLimit(3);
        pdt.setLoanAction("323f3");
        pdt.setProductName("feiwefe");
        pdt.setPoundageRate("f332r3");
        long beg = System.currentTimeMillis();
        PropertyUtilsBean bean = new PropertyUtilsBean();

        BeanCopier copier = BeanCopier.create(ProductDTO.class, LfProduct.class, false);
        for (int i=0;i<1000;i++) {
            LfProduct lfPdt = null;
//            try {
//                try {
//                    bean.copyProperties(lfPdt, pdt);
//                } catch (IllegalAccessException | InvocationTargetException e) {
//                    // TODO Auto-generated catch block
//                    e.printStackTrace();
//                }
//            } catch (NoSuchMethodException e) {
//                // TODO Auto-generated catch block
//                e.printStackTrace();
//            }
//            copier.copy(pdt, lfPdt, null);
            if (i==3) {
//                System.out.println(JacksonHelper.toJSON(lfPdt));
            }
            lfPdt = wrapper.map(pdt, LfProduct.class);
            lfPdt.setInputDate(new Date());
        }
        System.out.println(System.currentTimeMillis() - beg);

2500ms。

PropertyUtilsBean

        Mapper wrapper = new DozerBeanMapper();
        ProductDTO pdt = new ProductDTO();
        pdt.setIsConsignerCreditLimit(3);
        pdt.setLoanAction("323f3");
        pdt.setProductName("feiwefe");
        pdt.setPoundageRate("f332r3");
        long beg = System.currentTimeMillis();
        PropertyUtilsBean bean = new PropertyUtilsBean();

        BeanCopier copier = BeanCopier.create(ProductDTO.class, LfProduct.class, false);
        for (int i=0;i<1000;i++) {
            LfProduct lfPdt = new LfProduct();
            try {
                try {
                    bean.copyProperties(lfPdt, pdt);
                } catch (IllegalAccessException | InvocationTargetException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            } catch (NoSuchMethodException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
//            copier.copy(pdt, lfPdt, null);
            if (i==3) {
//                System.out.println(JacksonHelper.toJSON(lfPdt));
            }
//            lfPdt = wrapper.map(pdt, LfProduct.class);
            lfPdt.setInputDate(new Date());
        }
        System.out.println(System.currentTimeMillis() - beg);

240ms左右。

所以,因为绝大部分都是简单的复制拷贝,这种情况下,BeanCopyer>PropertyUtils>Dozer。

参考:

http://blog.csdn.net/jianhua0902/article/details/8155368

http://blog.csdn.net/liangrui1988/article/details/41802275

时间: 2024-10-09 20:02:10

java bean属性拷贝工具类比对(性能+功能)的相关文章

对象属性拷贝工具类的性能比较

一.对象属性拷贝工具类 ”天下武功,唯快不破“.在互联网行业中体现的更加淋淋尽致.我们在业务系统会经常遇到业务对象间属性的拷贝,对如外接口一般都使用特定的DTO对象,而不会使用领域模型,以避免两者的变动互相影响.我们不仅要关注“快”,还要注重CPU的稳定即避免CPU使用的大起大落现象.如何高效完成属性的拷贝并降低对CPU的使用率或避免CPU的抖动. 相关博文已经有很多,为什么还要自己在一篇类似的哪?原因有二:一是加深理解二是比较各自优劣.目前对象间属性的拷贝常用的方法大致如下: 手动拷贝(set

java读取属性配置文件工具类

import java.io.IOException; import java.io.InputStream; import java.util.Properties; /** * * 类: ProUtil <br> * 描述: 属性配置文件读取类 <br> * 作者: poseidon<br> * 版本: 1.0<br> * 时间: 2015-7-17 上午09:20:17 */ public class ProUtil { /* 私有构造方法,防止被实例

Java Bean 简介及其应用

Bean的中文含义是"豆子",顾名思义JavaBean是一段Java小程序.JavaBean实际上是指一种特殊的Java类,它通常用来实现一些比较常用的简单功能,并可以很容易的被重用或者是插入其他应用程序中去.所有遵循一定编程原则的Java类都可以被称作JavaBean. 一. Java Bean技术概述 Java Bean是基于Java的组件模型,由属性.方法和事件3部分组成.在该模型中,JavaBean可以被修改或与其他组件结合以生成新组件或完整的程序.它是一种Java类,通过封装

Apache Commons Beanutils教程一(访问Bean属性)

BeanUtils简要描述 beanutils,顾名思义,是java bean的一个工具类,可以帮助我们方便的读取(get)和设置(set)bean属性值.动态定义和访问bean属性: 细心的话,会发现其实JDK已经提供了一个java.beans包,同样可以实现以上功能,只不过使用起来比较麻烦,所以诞生了apache commons beanutils: 看源码就知道,其实apache commons beanutils就是基于jdk的java.beans包实现的. Java Bean 在介绍a

好程序员Java学习路线Java bean是个什么概念

好程序员Java学习路线Java bean是个什么概念,Bean的中文含义是"豆子",顾名思义JavaBean是一段Java小程序.JavaBean实际上是指一种特殊的Java类,它通常用来实现一些比较常用的简单功能,并可以很容易的被重用或者是插入其他应用程序中去.所有遵循一定编程原则的Java类都可以被称作JavaBean.一. Java Bean技术概述??????? Java Bean是基于Java的组件模型,由属性.方法和事件3部分组成.在该模型中,JavaBean可以被修改或

java bean 转换工具

考量要素: 1.简单的约定优于配置的同名属性copy 2.嵌套属性copy 3.flattern(扁平化)支持,要支持N层结构的copy到一层结构. 4.性能 如下这个网页,里面提到了好多工具. http://stackoverflow.com/questions/1432764/any-tool-for-java-object-to-object-mapping 注意到许多工具采用静态化的生成java字节码的方式,这样和hardcode性能所差无几了. id 描述 是否支持flattern 最

【小工具】根据定义的白名单字段进行Bean的拷贝

背景 Bean的拷贝一直有一些类可以使用,比如Apache的org.apache.commons.beanutils.BeanUtils或者Spring的org.springframework.beans.BeanUtils. 根据定义的白名单字段进行Bean的拷贝 我需要一个只拷贝我指定的字段的Bean拷贝,而Spring的org.springframework.beans.BeanUtils提供如下几个方法: 其中第2.3个是可以指定属性的,第2个指定可以通过Class指定,基本满足我的需求

一个强大易用的java bean之间属性复制框架--Dozer介绍

Dozer is a Java Bean to Java Bean mapper that recursively copies data from one object to another. Typically, these Java Beans will be of different complex types. 更多内容见:http://dozer.sourceforge.net/documentation/about.html 两个简单示例: map --> bean假设由reque

java bean 对象属性复制框架BeanMapping-01-入门案例

项目简介 Bean-Mapping 用于 java 对象属性赋值. 项目中经常需要将一个对象的属性,赋值到另一个对象中. 常见的工具有很多,但都多少不够简洁,要么不够强大. 特性 支持对象属性的浅拷贝 变更日志 变更日志 快速开始 准备 JDK1.8 及其以上版本 Maven 3.X 及其以上版本 maven 项目依赖 <dependency> <groupId>com.github.houbb</groupId> <artifactId>bean-mapp