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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM