几种Bean的复制方法性能比较

时间:2021-08-15 08:33:56

  由于项目对性能 速度要求很高,表中的字段也很多,存在一个复制方法,耗时相对比较长,经过测试,使用Apache,Spring等提供的方法 耗时较长,使用自己自定义的复制方法时间提升很多,现记录下。

1.pom.xml

几种Bean的复制方法性能比较几种Bean的复制方法性能比较
 1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
2 <modelVersion>4.0.0</modelVersion>
3 <groupId>com.xsjt.compare</groupId>
4 <artifactId>copy-property</artifactId>
5 <version>0.0.1-SNAPSHOT</version>
6
7 <dependencies>
8 <!-- apache -->
9 <dependency>
10 <groupId>commons-beanutils</groupId>
11 <artifactId>commons-beanutils</artifactId>
12 <version>1.8.3</version>
13 </dependency>
14
15 <!-- Spring -->
16 <dependency>
17 <groupId>org.springframework</groupId>
18 <artifactId>spring-beans</artifactId>
19 <version>4.3.8.RELEASE</version>
20 </dependency>
21
22 <!-- cglib -->
23 <dependency>
24 <groupId>cglib</groupId>
25 <artifactId>cglib</artifactId>
26 <version>3.2.3</version>
27 </dependency>
28
29 <!-- ezmorph -->
30 <dependency>
31 <groupId>net.sf.ezmorph</groupId>
32 <artifactId>ezmorph</artifactId>
33 <version>1.0.6</version>
34 </dependency>
35
36 </dependencies>
37 </project>
View Code

2.定义一个实体bean

 1 package com.xsjt.bean;
2
3 import java.io.Serializable;
4 import java.math.BigDecimal;
5 import java.util.Date;
6
7 /**
8 * 用户实体类
9 * @author Administrator
10 *
11 */
12 @SuppressWarnings("serial")
13 public class User implements Serializable{
14
15 private int id;
16 private String userName;
17 private String userPass;
18 private String phone;
19 private Date birth;
20 private BigDecimal totleMoney;
21 private String remark;
22
23 public User() {
24 super();
25 }
26
27 public User(int id, String userName, String userPass, String phone, Date birth, BigDecimal totleMoney, String remark) {
28 super();
29 this.id = id;
30 this.userName = userName;
31 this.userPass = userPass;
32 this.phone = phone;
33 this.birth = birth;
34 this.totleMoney = totleMoney;
35 this.remark = remark;
36 }
37
38 public int getId() {
39 return id;
40 }
41 public void setId(int id) {
42 this.id = id;
43 }
44 public String getUserName() {
45 return userName;
46 }
47 public void setUserName(String userName) {
48 this.userName = userName;
49 }
50 public String getUserPass() {
51 return userPass;
52 }
53 public void setUserPass(String userPass) {
54 this.userPass = userPass;
55 }
56 public String getPhone() {
57 return phone;
58 }
59 public void setPhone(String phone) {
60 this.phone = phone;
61 }
62 public Date getBirth() {
63 return birth;
64 }
65 public void setBirth(Date birth) {
66 this.birth = birth;
67 }
68 public BigDecimal getTotleMoney() {
69 return totleMoney;
70 }
71 public void setTotleMoney(BigDecimal totleMoney) {
72 this.totleMoney = totleMoney;
73 }
74 public String getRemark() {
75 return remark;
76 }
77 public void setRemark(String remark) {
78 this.remark = remark;
79 }
80
81 @Override
82 public String toString() {
83 return "User [id=" + id + ", userName=" + userName + ", userPass=" + userPass + ", phone=" + phone + ", birth=" + birth + ", totleMoney=" + totleMoney + ", remark=" + remark + "]";
84 }
85
86 }

3.自己定义的bean复制方法 

 1 package com.xsjt.util;
2
3 import java.lang.reflect.Field;
4 import java.math.BigDecimal;
5 import java.util.Date;
6 import com.xsjt.bean.User;
7
8 /**
9 * ClassName:CopyBeanProperty
10 * 在对象之间 进行属性值 复制
11 * Date: 2017年7月19日 下午5:53:07
12 * @author Joe
13 * @version
14 * @since JDK 1.8
15 */
16 public class CopyBeanProperty {
17
18 /**
19 * 将 旧的bean的值 赋值 给 新的bean
20 * @param oldObj
21 * @param newObj
22 */
23 public static void copyproperty(Object oldObj ,Object newObj){
24
25 Class<?> clz = oldObj.getClass();
26 Field[] cols = clz.getDeclaredFields();
27
28 String name = null;
29 Object value = null;
30 try {
31 for(Field col : cols){
32 if(!col.isAccessible()){
33 // 设置可访问
34 col.setAccessible(true);
35 }
36 name = col.getName();
37 value = col.get(oldObj);
38 // 赋值给 新的bean
39 setBeanProperty(name ,value ,newObj);
40 }
41 } catch (Exception e) {
42 e.printStackTrace();
43 }
44 }
45
46 /**
47 * 将 name 和 value 赋值给 新的bean
48 * @param name
49 * @param value
50 * @param newObj
51 * @throws SecurityException
52 * @throws NoSuchFieldException
53 * @throws IllegalAccessException
54 * @throws IllegalArgumentException
55 */
56 private static void setBeanProperty(String name, Object value, Object newObj) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
57 Class<?> clz = newObj.getClass();
58 Field col = clz.getDeclaredField(name);
59 if(!col.isAccessible()){
60 // 设置可访问
61 col.setAccessible(true);
62 }
63 col.set(newObj, value);
64 }
65
66 /**
67 * 循环输入 属性 和 值 ,测试的 时候 使用
68 * @param newObj
69 * @throws IllegalAccessException
70 * @throws IllegalArgumentException
71 */
72 private static void loopBeanProperty(Object newObj) throws IllegalArgumentException, IllegalAccessException{
73 Class<?> clz = newObj.getClass();
74 Field[] cols = clz.getDeclaredFields();
75 for(Field col : cols){
76 if(!col.isAccessible()){
77 // 设置可访问
78 col.setAccessible(true);
79 }
80 System.out.println(col.getName() + "-->" + col.get(newObj));
81 }
82 }
83
84 /**
85 * 测试
86 * @param args
87 */
88 public static void main(String[] args) {
89 User user = new User(1, "admin", "12345", "135555555555", new Date(), new BigDecimal(20000.88), "土豪");
90 try {
91 loopBeanProperty(user);
92 } catch (IllegalArgumentException e) {
93 e.printStackTrace();
94 } catch (IllegalAccessException e) {
95 e.printStackTrace();
96 }
97 }
98 }

4.各种bean复制方法的比较

 1 package com.xsjt.compare;
2
3 import java.math.BigDecimal;
4 import java.util.Date;
5 import org.apache.commons.beanutils.BeanUtils;
6 import com.xsjt.bean.User;
7 import com.xsjt.util.CopyBeanProperty;
8 import net.sf.cglib.beans.BeanCopier;
9 import net.sf.ezmorph.MorpherRegistry;
10 import net.sf.ezmorph.bean.BeanMorpher;
11
12 /**
13 * ClassName:CompareTest
14 * 测试 各种 复制 方法的性能
15 * Date: 2017年7月19日 下午5:53:07
16 * @author Joe
17 * @version
18 * @since JDK 1.8
19 */
20 public class CompareTest {
21
22 public static void main(String[] args) throws Exception {
23
24 // 1.使用 apache 的 复制 方法
25 User orig = new User(1, "admin", "12345", "135555555555", new Date(), new BigDecimal(20000.88), "土豪");
26 User dest = new User();
27 long start = System.currentTimeMillis();
28 BeanUtils.copyProperties(dest, orig);
29 System.out.println("1.apache的方法 花费的时间:" + (System.currentTimeMillis() - start) + "ms");
30 System.out.println("dest==" + dest);
31
32 System.out.println("--------------------------------我是分割线------------------------------------------------");
33
34 // 2.使用 spring 的 复制方法
35 User source = new User(1, "admin", "12345", "135555555555", new Date(), new BigDecimal(20000.88), "土豪");
36 User target = new User();
37 start = System.currentTimeMillis();
38 org.springframework.beans.BeanUtils.copyProperties(source, target);
39 System.out.println("2.spring的方法 花费的时间:" + (System.currentTimeMillis() - start) + "ms");
40 System.out.println("target==" + target);
41
42 System.out.println("--------------------------------我是分割线------------------------------------------------");
43
44 // 3.使用 cglib 的复制方法
45 User source2 = new User(1, "admin", "12345", "135555555555", new Date(), new BigDecimal(20000.88), "土豪");
46 User target2 = new User();
47 start = System.currentTimeMillis();
48 BeanCopier.create(source2.getClass(), target2.getClass(), false).copy(source2, target2, null);
49 System.out.println("3.cglib的方法 花费的时间:" + (System.currentTimeMillis() - start) + "ms");
50 System.out.println("target2==" + target2);
51
52 System.out.println("--------------------------------我是分割线------------------------------------------------");
53
54 // 4.使用 EZMorph 的复制方法
55 User source3 = new User(1, "admin", "12345", "135555555555", new Date(), new BigDecimal(20000.88), "土豪");
56 User target3 = new User();
57 start = System.currentTimeMillis();
58 MorpherRegistry registry = new MorpherRegistry();
59 registry.registerMorpher(new BeanMorpher(User.class, registry));
60 target3 = (User) registry.morph(User.class, source3);
61 System.out.println("4.EZMorph的方法 花费的时间:" + (System.currentTimeMillis() - start) + "ms");
62 System.out.println("target3==" + target3);
63
64 System.out.println("--------------------------------我是分割线------------------------------------------------");
65
66 // 5.使用 自定义 的复制方法
67 User oldUser = new User(1, "admin", "12345", "135555555555", new Date(), new BigDecimal(20000.88), "土豪");
68 User newUser = new User();
69 start = System.currentTimeMillis();
70 CopyBeanProperty.copyproperty(oldUser, newUser);
71 System.out.println("5.自定义的方法 花费的时间:" + (System.currentTimeMillis() - start) + "ms");
72 System.out.println("newUser==" + newUser);
73 }
74 }

5.运行结果展示

  几种Bean的复制方法性能比较

  自定义的复制方法,使用了Java的反射机制实现,虽然其他的方法也是通过反射实现。但是自己定义的耗时时间最少,记录下,以备后用。

6.源码下载

  https://git.oschina.net/xbq8023/copy-property.git