天天看點

幾種Bean的複制方法性能比較

  由于項目對性能 速度要求很高,表中的字段也很多,存在一個複制方法,耗時相對比較長,經過測試,使用Apache,Spring等提供的方法 耗時較長,使用自己自定義的複制方法時間提升很多,現記錄下。

1.pom.xml

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/xbq168/copy-property.git