一、前提
- bean 有10个属性
各方法对应组件及版本说明:
方法名 | 所属模块 | 模块版本号 |
---|---|---|
apacheBeanUtilsCopyTest | commons-beanutils | 1.9.4 |
springBeanUtilsCopyTest | spring-beans | 5.1.12.RELEASE |
cglibBeanCopierTest | cglib | 3.3.0 |
springBeanCopierTest | spring-core | 5.1.12.RELEASE |
getSetTest | jdk | 8 |
mapstructTest | mapstruct | 1.3.1.Final |
二、结论
对比常用几种bean copy得出如下结论:
- 通过Set/Get、cglib bean copier、mapstruct进行属性copy,其性能基本持平。
- spring core包中的bean copier的copy相比上面三种,性能略有下降,但不大。
- spring bean包中的bean utils的copy相比上面四种,性能有较大差距,性能大概慢21.5倍左右。
- 性能最差为apache common-beanutils的bean utils的copy,性能和最高差距大概 慢460倍,比倒数第二慢21倍。
三、测试结果:
Benchmark Mode Cnt Score Error Units
BeanCopyTest.apacheBeanUtilsCopyTest thrpt 9 542.549 ± 43.868 ops/ms
BeanCopyTest.cglibBeanCopierTest thrpt 9 250689.491 ± 3690.880 ops/ms
BeanCopyTest.getSetTest thrpt 9 250695.090 ± 4487.843 ops/ms
BeanCopyTest.mapstructTest thrpt 9 249712.148 ± 4686.468 ops/ms
BeanCopyTest.springBeanCopierTest thrpt 9 238908.247 ± 37465.537 ops/ms
BeanCopyTest.springBeanUtilsCopyTest thrpt 9 11528.375 ± 797.580 ops/ms
四、测试代码
Person/Person内只有10个属性,名称一致,太简单不再放出,测试代码如下:
import net.sf.cglib.beans.BeanCopier;
import org.apache.commons.beanutils.BeanUtils;
import org.openjdk.jmh.annotations.*;
import java.lang.reflect.InvocationTargetException;
import java.util.Date;
import java.util.concurrent.TimeUnit;
@State(Scope.Benchmark)
@BenchmarkMode(value = Mode.Throughput)
@Warmup(iterations = 1)
@Measurement(iterations = 3, time = 5, timeUnit = TimeUnit.SECONDS)
@Threads(10)
@Fork(3)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class BeanCopyTest {
private Person sourcePerson;
private BeanCopier beanCopier = BeanCopier.create(Person.class, Person2.class, false);
private org.springframework.cglib.beans.BeanCopier beanCopier2 = org.springframework.cglib.beans.BeanCopier.create(
Person.class, Person2.class, false);
@Setup
public void init() {
sourcePerson = new Person();
sourcePerson.setId(1000021L);
sourcePerson.setCode("IM-Test-1001");
sourcePerson.setName("小明");
sourcePerson.setCountry("中国");
sourcePerson.setCity("上海");
sourcePerson.setEmail("xiaoming.wang@demo.com");
sourcePerson.setMobile("18810088888");
sourcePerson.setPosition("闲杂人员");
sourcePerson.setUserType(2);
sourcePerson.setBirthday(new Date(1990, 10, 24));
}
@Benchmark
public Person2 apacheBeanUtilsCopyTest() throws InvocationTargetException, IllegalAccessException {
Person2 target = new Person2();
BeanUtils.copyProperties(target, sourcePerson);
return target;
}
@Benchmark
public Person2 springBeanUtilsCopyTest() {
Person2 target = new Person2();
org.springframework.beans.BeanUtils.copyProperties(sourcePerson, target);
return target;
}
@Benchmark
public Person2 cglibBeanCopierTest() {
Person2 target = new Person2();
beanCopier.copy(sourcePerson, target, null);
return target;
}
@Benchmark
public Person2 springBeanCopierTest() {
Person2 target = new Person2();
beanCopier2.copy(sourcePerson, target, null);
return target;
}
@Benchmark
public Person2 getSetTest() {
Person2 target = new Person2();
target.setId(sourcePerson.getId());
target.setBirthday(sourcePerson.getBirthday());
target.setCity(sourcePerson.getCity());
target.setCode(sourcePerson.getCode());
target.setCountry(sourcePerson.getCountry());
target.setEmail(sourcePerson.getEmail());
target.setMobile(sourcePerson.getMobile());
target.setUserType(sourcePerson.getUserType());
target.setPosition(sourcePerson.getPosition());
target.setName(sourcePerson.getName());
return target;
}
@Benchmark
public Person2 mapstructTest() {
Person2 target = PersonMapping.INSTANCE.castToPerson2(sourcePerson);
return target;
}
}