allTypes_mappingTools

博客介绍了多种 Bean 映射方式,包括 apache BeanUtils、spring BeanUtils、cglib 及 mapstruct 等方式进行映射,还提及了 cglib 的 WrapperBeanCopier 缓存化,对比了 cglib.BeanCopier 和 spring.BeanUtilsBeanCopie 的速度,并给出了相关代码示例及参考文章和 github 地址。

github地址:
https://github.com/wei198621/allTypes_mappingTools
参考文章:
https://www.cnblogs.com/songhaibin/p/13382799.html
参考文章(mapstruct)
https://www.bbsmax.com/A/8Bz8PVq6zx/

apache BeanUtils 进行mapping

代码

  <dependencies>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.6</version>
        </dependency>

        <!--//org.apache.commons.beanutils.BeanUtils-->
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.9.3</version>
        </dependency>
    </dependencies>
package com.tz.leo.apcheBeanUtils;

import com.tz.leo.apcheBeanUtils.beans.Order;
import com.tz.leo.apcheBeanUtils.beans.OrderQueryParam;
import org.apache.commons.beanutils.BeanUtils;

import java.lang.reflect.InvocationTargetException;



/**
 * Author: tz_wl
 * Date: 2020/8/12 16:55
 * Content:
 */
public class ApacheBeanUtilsTest {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
        Order order = new Order();
        order.setId(12345L);
        order.setOrderSn("orderSn");
        order.setOrderType(0);
        order.setReceiverKeyword("keyword");
        order.setSourceType(1);
        order.setStatus(2);

        OrderQueryParam orderQueryParam = new OrderQueryParam();
        BeanUtils.copyProperties(orderQueryParam,order);  // (dest,source)
        System.out.println("orderQueryParam is : " + orderQueryParam);

    }
}

orderQueryParam is : OrderQueryParam(id=12345, orderSn=orderSn, receiverKeyword=keyword, receiverKeyword2=null, status=2, orderType=0, orderType2=null, sourceType=1)

spring BeanUtils 进行mapping

代码

   <dependencies>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.6</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>

    </dependencies>
package com.tz.leo.springBeanUtils;


import com.tz.leo.springBeanUtils.beans.Order;
import com.tz.leo.springBeanUtils.beans.OrderQueryParam;
import org.springframework.beans.BeanUtils;

import java.lang.reflect.InvocationTargetException;


/**
 * Author: tz_wl
 * Date: 2020/8/12 16:55
 * Content:
 */
public class SpringBeanUtilsTest {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
        Order order = new Order();
        order.setId(12345L);
        order.setOrderSn("orderSn");
        order.setOrderType(0);
        order.setReceiverKeyword("keyword");
        order.setSourceType(1);
        order.setStatus(2);

        OrderQueryParam orderQueryParam = new OrderQueryParam();
        BeanUtils.copyProperties(order,orderQueryParam);  //(source,dest)
        System.out.println("通过springframework的BeanUtils,  orderQueryParam is : " + orderQueryParam);

    }
}

cglib 进行 mapping

代码

    <dependencies>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.2.10</version>
        </dependency>
        <dependency>
            <groupId>com.esotericsoftware</groupId>
            <artifactId>reflectasm</artifactId>
            <version>1.11.7</version>
        </dependency>
    </dependencies>
package com.tz.leo.CglibBeanCopier01;

import com.tz.leo.CglibBeanCopier01.beans.User;
import com.tz.leo.CglibBeanCopier01.beans.UserDto;
import net.sf.cglib.beans.BeanCopier;

/**
 * Author: tz_wl
 * Date: 2020/8/12 18:27
 * Content:
 */
public class BeanCopierTest01 {
    public static void main(String[] args) {
        CopyUser2UserDto();
    }

    /**
    *@Description:  User.age  (int)   UserDto.age (int)
     * User  与  UserDto age  name  都是相同类型 所以可以从User映射到UserDto
    *@Param:
    *@return:
    *@date: 2020/8/12
    */
    private static void CopyUser2UserDto() {
        final BeanCopier beanCopier = BeanCopier.create(User.class, UserDto.class, false);
        User user = new User();
        user.setAge(10)        ;
        user.setName("zhangsan01");
        UserDto userDto = new UserDto();
        beanCopier.copy(user,userDto,null);

        System.out.println("======CopyUser2UserDto========");
        System.out.println(userDto.getAge());
        System.out.println(userDto.getName());
        System.out.println("======CopyUser2UserDto========");
    }
}

在这里插入图片描述

package com.tz.leo.CglibBeanCopier03withWrapper;

import com.tz.leo.CglibBeanCopier03withWrapper.beans.Account;
import com.tz.leo.CglibBeanCopier03withWrapper.beans.AccountDto;
import net.sf.cglib.beans.BeanCopier;
import java.math.BigDecimal;
import java.util.Date;

/**
 * Author: tz_wl
 * Date: 2020/8/12 19:09
 * Content:
 */
public class BeanCopier3Test {
    public static void main(String[] args) {
        CopeOrigional();
        CopeWithWrapper();
    }

    /**
    *@Description:   原始的copy 方法  
    *@Param: 
    *@return: 
    *@date: 2020/8/12
    */
    private static void CopeOrigional() {
        Account account = new Account();
        account.setId(1);
        account.setCreateTime(new Date());
        account.setBalance(BigDecimal.valueOf(4000L));

        BeanCopier copier = BeanCopier.create(Account.class, AccountDto.class, false);
        AccountDto accountDto = new AccountDto();
        copier.copy(account, accountDto, null);

        System.out.println("==============CopeSimple1================");
        System.out.println(accountDto.getId());            //1
        System.out.println(accountDto.getBalance());       //null
        System.out.println(accountDto.getCreateTime());    //null
        System.out.println("=============CopeSimple1=================");
    }
  
    /**
    *@Description: 封装copy类 增加缓存 效果更好 
    *@Param: 
    *@return: 
    *@date: 2020/8/12
    */
    private static void CopeWithWrapper() {
        Account account = new Account();
        account.setId(1);
        account.setCreateTime(new Date());
        account.setBalance(BigDecimal.valueOf(4000L));
        AccountDto accountDto = new AccountDto();
        WrapperBeanCopier.copyProperties(account,accountDto);
        System.out.println("==============CopeWithWrapper================");
        System.out.println(accountDto.getId());            //1
        System.out.println(accountDto.getBalance());       //null
        System.out.println(accountDto.getCreateTime());    //null
        System.out.println("=============CopeWithWrapper=================");
    }
}

WrapperBeanCopier–BeanCopier缓存化

package com.tz.leo.CglibBeanCopier03withWrapper;

import com.esotericsoftware.reflectasm.ConstructorAccess;
import net.sf.cglib.beans.BeanCopier;


import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static java.lang.String.format;

/**
 * Author: tz_wl
 * Date: 2020/8/12 19:09
 * Content:
 * BeanCopier拷贝速度快,性能瓶颈出现在创建BeanCopier实例的过程中。 所以,把创建过的BeanCopier实例放到缓存中,下次可以直接获取,提升性能:
 *
 */


public class WrapperBeanCopier {

    private WrapperBeanCopier() {
        //do nothing
    }

    private static final Map<String, BeanCopier> BEAN_COPIER_CACHE = new ConcurrentHashMap<String, BeanCopier>();

    private static final Map<String, ConstructorAccess> CONSTRUCTOR_ACCESS_CACHE = new ConcurrentHashMap<String, ConstructorAccess>();

    public static void copyProperties(Object source, Object target) {
        BeanCopier copier = getBeanCopier(source.getClass(), target.getClass());
        copier.copy(source, target, null);
    }

    private static BeanCopier getBeanCopier(Class sourceClass, Class targetClass) {
        String beanKey = generateKey(sourceClass, targetClass);
        BeanCopier copier = null;
        if (!BEAN_COPIER_CACHE.containsKey(beanKey)) {
            copier = BeanCopier.create(sourceClass, targetClass, false);
            BEAN_COPIER_CACHE.put(beanKey, copier);
        } else {
            copier = BEAN_COPIER_CACHE.get(beanKey);
        }
        return copier;
    }

    /**
     * 两个类的全限定名拼接起来构成Key
     *
     * @param sourceClass
     * @param targetClass
     * @return
     */
    private static String generateKey(Class<?> sourceClass, Class<?> targetClass) {
        return sourceClass.getName() + targetClass.getName();
    }

    public static <T> T copyProperties(Object source, Class<T> targetClass) {
        T t = null;
        try {
            t = targetClass.newInstance();
        } catch (Exception e) {
            throw new RuntimeException(format("Create new instance of %s failed: %s", targetClass, e.getMessage()));
        }
        copyProperties(source, t);
        return t;
    }

    public static <T> List<T> copyPropertiesOfList(List<?> sourceList, Class<T> targetClass) {
        if (sourceList == null || sourceList.isEmpty()) {
            return Collections.emptyList();
        }
        ConstructorAccess<T> constructorAccess = getConstructorAccess(targetClass);
        List<T> resultList = new ArrayList<T>(sourceList.size());
        for (Object o : sourceList) {
            T t = null;
            try {
                t = constructorAccess.newInstance();
                copyProperties(o, t);
                resultList.add(t);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        return resultList;
    }

    private static <T> ConstructorAccess<T> getConstructorAccess(Class<T> targetClass) {
        ConstructorAccess<T> constructorAccess = CONSTRUCTOR_ACCESS_CACHE.get(targetClass.getName());
        if (constructorAccess != null) {
            return constructorAccess;
        }
        try {
            constructorAccess = ConstructorAccess.get(targetClass);
            constructorAccess.newInstance();
            CONSTRUCTOR_ACCESS_CACHE.put(targetClass.toString(), constructorAccess);
        } catch (Exception e) {
            throw new RuntimeException(format("Create new instance of %s failed: %s", targetClass, e.getMessage()));
        }
        return constructorAccess;
    }

}

cglib.BeanCopier VS spring.BeanUtilsBeanCopie 速度非常快

    BeanUtils start time is :1597236554316
    BeanUtils end time is   :1597236554637
    BeanUtils took time: 321(ms)
    ====================================================
    BeanCopie start time is :1597236554667
    BeanCopie rend time is  :1597236554667
    BeanCopier took time: 0(ms)
package com.tz.leo.BeanCopierVSBeanUtils;

import com.tz.leo.BeanCopierVSBeanUtils.beans.User;
import com.tz.leo.BeanCopierVSBeanUtils.beans.UserDto;
import net.sf.cglib.beans.BeanCopier;
import org.springframework.beans.BeanUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * Author: tz_wl
 * Date: 2020/8/12 20:33
 * Content:  BeanCopier  速度非常快
 */
public class appTest {
    public static void main(String[] args) {
        List<User> list1 = new ArrayList<User>(9900000);
        for (int i = 0; i < 100; i++) {
            User po = new User();
            po.setAge(1);
            po.setName("lili"+ (new Random()).toString());
            list1.add(po);
        }

        //*************************** BeanUtils  9900000 用时测试  ************************************
        long startBeanUtils = System.currentTimeMillis();
        System.out.println("BeanUtils start time is :" +startBeanUtils);
        List<UserDto> list2 = new ArrayList<UserDto>(9900000);
        for (User user : list1) {
            UserDto dto = new UserDto();
            BeanUtils.copyProperties(user, dto);   //270 ms
            list2.add(dto);
        }

        long endBeanUtils =System.currentTimeMillis();
        System.out.println("BeanUtils end time is   :" + endBeanUtils );
        System.out.printf("BeanUtils took time: %d(ms)%n", endBeanUtils - startBeanUtils);

        //************************** BeanCopier  9900000 用时测试 *************************************
        System.out.println("====================================================");
        BeanCopier copier = BeanCopier.create(User.class, UserDto.class, false);
        long startBeanCopier = System.currentTimeMillis();
        List<UserDto> list3 = new ArrayList<UserDto>(9900000);
        System.out.println("BeanCopie start time is :" +startBeanCopier);
        for (User user : list1) {
            UserDto dto = new UserDto();
            copier.copy(user, dto, null);      //20 ms
            list3.add(dto);
        }
        long endBeanCopier =System.currentTimeMillis();
        System.out.println("BeanCopie rend time is  :" + endBeanCopier );
        System.out.printf("BeanCopier took time: %d(ms)%n", endBeanCopier - startBeanCopier);

    }
}

mapstruct 方式进行映射

代码


    <properties>
        <org.mapstruct.version>1.3.0.Final</org.mapstruct.version>
    </properties>


    <dependencies>

        <!--//需要将编译环境设置为1.8及以上方式编译-->
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-jdk8</artifactId>
            <version>${org.mapstruct.version}</version>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>${org.mapstruct.version}</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.6</version>
        </dependency>


    </dependencies>

package com.tz.leo.MapStruts.mappers;

import com.tz.leo.MapStruts.beans.Order;
import com.tz.leo.MapStruts.beans.OrderQueryParam;
import org.mapstruct.Mapper;

/**
 * Author: tz_wl
 * Date: 2020/8/12 16:07
 * Content:
 */
//只有一个要求, 在接口上写 @Mapper 注解即可
@Mapper
public interface OrderMapper {
    OrderQueryParam entity2queryParam(Order order);
}

package com.tz.leo.MapStruts;

import com.tz.leo.MapStruts.beans.Order;
import com.tz.leo.MapStruts.beans.OrderQueryParam;
import com.tz.leo.MapStruts.mappers.OrderMapper;
import org.mapstruct.factory.Mappers;

/**
 * Author: tz_wl
 * Date: 2020/8/12 16:08
 * Content:
 */
public class MapStructTest {
    public static void main(String[] args) {
        Order order = new Order();
        order.setId(12345L);
        order.setOrderSn("orderSn");
        order.setOrderType(0);
        order.setReceiverKeyword("keyword");
        order.setSourceType(1);
        order.setStatus(2);
        OrderMapper mapper = Mappers.getMapper(OrderMapper.class);
        OrderQueryParam orderQueryParam = mapper.entity2queryParam(order);
        System.out.println(orderQueryParam.getOrderSn());
        System.out.println(orderQueryParam.getReceiverKeyword());
    }

}

代码

// An highlighted block
var foo = 'bar';
// An highlighted block
var foo = 'bar';
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值