其他
Java Bean Copy性能对比
点击上方☝SpringForAll社区 轻松关注!
本文来源:http://rrd.me/g6P3V
常用的对象复制方法
Apache BeanUtils Spring BeanUtils Spring BeanCopier Cglib BeanCopier Hutool BeanUtil get/set
测试环境
Java8 4核16G台式机
依赖
<!-- Spring BeanUtils, Spring Copier -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.7.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>Copy
<!-- Apache BeanUtils -->
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
<version>1.9.4</version>
</dependency>Copy
<!-- Cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>Copy
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.3.5</version>
</dependency>Copy
开始测试
定义两个实体类
package xyz.easyboot.demo;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* @author wujiawei0926@yeah.net
* @see
* @since 2020/5/15
*/
public class FromVo {
public static FromVo create(){
FromVo vo = new FromVo();
vo.setDate(LocalDateTime.now());
vo.setMoney(new BigDecimal(10000));
vo.setId(9999);
vo.setName("演示");
return vo;
}
private String name;
private Integer id;
private LocalDateTime date;
private BigDecimal money;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public LocalDateTime getDate() {
return date;
}
public void setDate(LocalDateTime date) {
this.date = date;
}
public BigDecimal getMoney() {
return money;
}
public void setMoney(BigDecimal money) {
this.money = money;
}
}Copy
package xyz.easyboot.demo;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
* @author wujiawei0926@yeah.net
* @see
* @since 2020/5/15
*/
public class ToVo {
public static ToVo create(){
ToVo vo = new ToVo();
vo.setDate(LocalDateTime.now());
vo.setMoney(new BigDecimal(10000));
vo.setId(9999);
vo.setName("演示");
return vo;
}
private String name;
private Integer id;
private LocalDateTime date;
private BigDecimal money;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public LocalDateTime getDate() {
return date;
}
public void setDate(LocalDateTime date) {
this.date = date;
}
public BigDecimal getMoney() {
return money;
}
public void setMoney(BigDecimal money) {
this.money = money;
}
}Copy
Apache BeanUtils
package xyz.easyboot.demo;
import org.apache.commons.beanutils.BeanUtils;
import java.lang.reflect.InvocationTargetException;
/**
* @author wujiawei0926@yeah.net
* @see
* @since 2020/5/15
*/
public class ApacheBeanUtilsDemo {
public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
for (int j = 0; j < 5; j++) {
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
FromVo from = FromVo.create();
ToVo to = new ToVo();
BeanUtils.copyProperties(to, from);
}
long end = System.currentTimeMillis();
System.out.println("processing: " + (end - start));
}
}
}Copy
Spring BeanUtils
package xyz.easyboot.demo;
import org.springframework.beans.BeanUtils;
/**
* @author wujiawei0926@yeah.net
* @see
* @since 2020/5/15
*/
public class SpringBeanUtilsDemo {
public static void main(String[] args) {
for (int j = 0; j < 5; j++) {
long start = System.currentTimeMillis();
for (int i = 0; i < 10000; i++) {
FromVo from = FromVo.create();
ToVo to = new ToVo();
BeanUtils.copyProperties(from, to);
}
long end = System.currentTimeMillis();
System.out.println("processing: " + (end - start));
}
}
}Copy
Spring BeanCopier
package xyz.easyboot.demo;
import org.springframework.cglib.beans.BeanCopier;
/**
* @author wujiawei0926@yeah.net
* @see
* @since 2020/5/15
*/
public class SpringBeanCopierDemo {
public static void main(String[] args) {
final BeanCopier copier = BeanCopier.create(FromVo.class, ToVo.class, false);
for (int j = 0; j < 5; j++) {
long start = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
FromVo from = FromVo.create();
ToVo to = new ToVo();
copier.copy(from, to, null);
}
long end = System.currentTimeMillis();
System.out.println(end - start);
}
}
}Copy
Cglib BeanCopier
package xyz.easyboot.demo;
import net.sf.cglib.beans.BeanCopier;
/**
* @author wujiawei0926@yeah.net
* @see
* @since 2020/5/15
*/
public class CglibBeanCopierDemo {
public static void main(String[] args) {
final BeanCopier copier = BeanCopier.create(FromVo.class, ToVo.class, false);
for (int j = 0; j < 5; j++) {
long start = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
FromVo from = FromVo.create();
ToVo to = new ToVo();
copier.copy(from, to, null);
}
long end = System.currentTimeMillis();
System.out.println(end - start);
}
}
}Copy
Hutool BeanUtil
package xyz.easyboot.demo;
import cn.hutool.core.bean.BeanUtil;
/**
* @author wujiawei0926@yeah.net
* @see
* @since 2020/5/21
*/
public class HutoolBeanUtilDemo {
public static void main(String[] args) {
for (int j = 0; j < 10000000; j++) {
long start = System.currentTimeMillis();
for (int i = 0; i < 10; i++) {
FromVo from = FromVo.create();
ToVo to = new ToVo();
BeanUtil.copyProperties(from, to);
}
long end = System.currentTimeMillis();
System.out.println(end - start);
}
}
}Copy
Get/Set
package xyz.easyboot.demo;
/**
* @author wujiawei0926@yeah.net
* @see
* @since 2020/5/15
*/
public class GetSetDemo {
public static void main(String[] args) {
for (int j = 0; j < 5; j++) {
long start = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
FromVo from = FromVo.create();
ToVo to = new ToVo();
to.setDate(from.getDate());
to.setId(from.getId());
to.setMoney(from.getMoney());
to.setName(from.getName());
}
long end = System.currentTimeMillis();
System.out.println(end - start);
}
}
}Copy
测试报告
结论
可以看到跟网上的结论还是有些区别的,我的测试环境和依赖版本是导致区别的原因之一,当然也可能是我的测试方法不对。
在次数很少的场景下更推荐 Spring Beanutils
Spring BeanCopier
和Cblib BeanCopier
的性能相差无几次数非常多的场景中, get/set
、BeanCopier
的速度差不多,但考虑到易用性,更推荐使用BeanCopier
Apache Beanutils
无疑是最慢的,这点与网上的结论完全一致国产的 Hutool BeanUtil
在执行次数较少的场景下还是值得一试的,但测试10000000次时出现了明显的速度问题
源码地址
https://github.com/wuuJiawei/springboot-demos/tree/master/bean-copy-test/src/main/java/xyz/easyboot/demo
参考文献
你还在用BeanUtils进行对象属性拷贝?
Java Bean Copy组件的性能比较
墙裂推荐
【深度】互联网技术人的社群,点击了解!
关注公众号,回复“spring”有惊喜!!!
如果资源对你有帮助的话