激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術(shù)及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - 基于Beanutils.copyProperties()的用法及重寫提高效率

基于Beanutils.copyProperties()的用法及重寫提高效率

2021-12-13 13:22菜鳥凱一枚 Java教程

這篇文章主要介紹了Beanutils.copyProperties( )的用法及重寫提高效率的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

Beanutils.copyProperties()用法及重寫提高效率

特別說明本文介紹的是Spring(import org.springframework.beans.BeanUtils)中的BeanUtils.copyProperties(A,B)方法。是將A中的值賦給B。apache(org.apache.commons.beanutils.BeanUtils)中的BeanUtils.copyProperties(A,B)方法是將B中的值賦值給A。

一、簡介

BeanUtils提供對Java反射和自省API的包裝。其主要目的是利用反射機制對JavaBean的屬性進行處理。我們知道,一個JavaBean通常包含了大量的屬性,很多情況下,對JavaBean的處理導致大量get/set代碼堆積,增加了代碼長度和閱讀代碼的難度。

二、用法

如果你有兩個具有很多相同屬性的JavaBean,一個很常見的情況就是Struts里的PO對象(持久對象)和對應的ActionForm。例如:一個用戶注冊頁面,有一個User實體類和一個UserActionForm,我們一般會在Action里從ActionForm構(gòu)造一個PO對象,傳統(tǒng)的方式是使用類似下面的語句對屬性逐個賦值:

// 獲取 ActionForm 表單數(shù)據(jù)  
UserActionForm uForm = (UserActionForm) form; 
// 構(gòu)造一個User對象  
User user = new User();  
// 逐一賦值  
user.setUsername(uForm.getUsername);  
user.setPassword(uForm.getPassword);  
user.setAge(uForm.getAge);    
...........  
...........  
// 然后調(diào)用JDBC、或操作Hibernate 持久化對象User到數(shù)據(jù)庫  
HibernateDAO.save(user); 

通過這樣的方法如果表單數(shù)據(jù)N多、100、1000(夸張點。哈哈)、、、、那我們不是要寫100、、、1000行set、get了。誰都

不愿意這樣做。

而我們使用 BeanUtils.copyProperties() 方法以后,代碼量大大的減少,而且整體程序看著也簡潔明朗,代碼如下:

// 獲取 ActionForm 表單數(shù)據(jù)  
UserActionForm uForm = (UserActionForm) form;      
// 構(gòu)造一個User對象  
User user = new User();    
BeanUtils.copyProperties(uForm,user);    
// 然后調(diào)用JDBC、或操作Hibernate 持久化對象User到數(shù)據(jù)庫  
HibernateDAO.save(user); 

注:如果User和UserActionForm 間存在名稱不相同的屬性,則BeanUtils不對這些屬性進行處理,需要手動處理。例如:

User類里面有個createDate 創(chuàng)建時間字段,而UserActionForm里面無此字段。BeanUtils.copyProperties()不會對此字段做任何處理。必須要自己手動處理。

user.setModifyDate(new Date());  

三、重寫

ReflectASM,高性能的反射:

什么是ReflectASM ReflectASM是一個很小的java類庫,主要是通過asm生產(chǎn)類來實現(xiàn)java反射,執(zhí)行速度非常快,看了網(wǎng)上很多和反射的對比,覺得ReflectASM比較神奇,很想知道其原理,下面介紹下如何使用及原理;

public static void main(String[] args) {    
      User user = new User();    
      //使用reflectasm生產(chǎn)User訪問類    
      MethodAccess access = MethodAccess.get(User.class);    
      //invoke setName方法name值    
      access.invoke(user, "setName", "張三");    
      //invoke getName方法 獲得值    
      String name = (String)access.invoke(user, "getName", null);    
      System.out.println(name);    
  }    

原理

上面代碼的確實現(xiàn)反射的功能,代碼主要的核心是 MethodAccess.get(User.class);

看了下源碼,這段代碼主要是通過asm生產(chǎn)一個User的處理類 UserMethodAccess(這個類主要是實現(xiàn)了invoke方法)的ByteCode,然后獲得該對象,通過上面的invoke操作user類。

private static Map<Class, MethodAccess> methodMap = new HashMap<Class, MethodAccess>();    
  private static Map<String, Integer> methodIndexMap = new HashMap<String, Integer>(); 
  private static Map<Class, List<String>> fieldMap = new HashMap<Class, List<String>>();  
  public static void copyProperties(Object desc, Object orgi) {  
      MethodAccess descMethodAccess = methodMap.get(desc.getClass());  
      if (descMethodAccess == null) {  
          descMethodAccess = cache(desc);  
      }  
      MethodAccess orgiMethodAccess = methodMap.get(orgi.getClass());  
      if (orgiMethodAccess == null) {  
          orgiMethodAccess = cache(orgi);  
      }  

      List<String> fieldList = fieldMap.get(orgi.getClass());  
      for (String field : fieldList) {  
          String getKey = orgi.getClass().getName() + "." + "get" + field;  
          String setkey = desc.getClass().getName() + "." + "set" + field;  
          Integer setIndex = methodIndexMap.get(setkey);  
          if (setIndex != null) {  
              int getIndex = methodIndexMap.get(getKey);  
              // 參數(shù)一需要反射的對象  
              // 參數(shù)二class.getDeclaredMethods 對應方法的index  
              // 參數(shù)對三象集合  
              descMethodAccess.invoke(desc, setIndex.intValue(),  
                      orgiMethodAccess.invoke(orgi, getIndex));  
          }  
      }  
  }  

  // 單例模式  
  private static MethodAccess cache(Object orgi) {  
      synchronized (orgi.getClass()) {  
          MethodAccess methodAccess = MethodAccess.get(orgi.getClass());  
          Field[] fields = orgi.getClass().getDeclaredFields();  
          List<String> fieldList = new ArrayList<String>(fields.length);  
          for (Field field : fields) {  
              if (Modifier.isPrivate(field.getModifiers())  
                      && !Modifier.isStatic(field.getModifiers())) { // 是否是私有的,是否是靜態(tài)的  
                  // 非公共私有變量  
                  String fieldName = StringUtils.capitalize(field.getName()); // 獲取屬性名稱  
                  int getIndex = methodAccess.getIndex("get" + fieldName); // 獲取get方法的下標  
                  int setIndex = methodAccess.getIndex("set" + fieldName); // 獲取set方法的下標  
                  methodIndexMap.put(orgi.getClass().getName() + "." + "get"  
                          + fieldName, getIndex); // 將類名get方法名,方法下標注冊到map中  
                  methodIndexMap.put(orgi.getClass().getName() + "." + "set"  
                          + fieldName, setIndex); // 將類名set方法名,方法下標注冊到map中  
                  fieldList.add(fieldName); // 將屬性名稱放入集合里  
              }  
          }  
          fieldMap.put(orgi.getClass(), fieldList); // 將類名,屬性名稱注冊到map中  
          methodMap.put(orgi.getClass(), methodAccess);  
          return methodAccess;  
      }  
  } 

執(zhí)行1000000條效率80幾毫秒,效率已經(jīng)沒問題了。

 

BeanUtils.copyProperties 使用注意

首先結(jié)論說在前頭, BeanUtils.copyProperties 是淺拷貝 。

基于Beanutils.copyProperties()的用法及重寫提高效率

為什么今天我還想把這個BeanUtils.copyProperties 的使用拿出來軍訓。

因為我意識到了大家(部分)對深拷淺拷還是不清晰,不知道具體的影響。

示例演示

第一個類:

基于Beanutils.copyProperties()的用法及重寫提高效率

第二個類:

基于Beanutils.copyProperties()的用法及重寫提高效率

注意!! 第二個類里面有使用第一個類。

開始進行示例

  public static void main(String[] args) { 
      /**
       * 模擬數(shù)據(jù) A  complexObject
       */
      ComplexObject complexObjectA=new ComplexObject();
      complexObjectA.setNickName("張一");
      SimpleObject simpleObject=new SimpleObject();
      simpleObject.setName("李四");
      simpleObject.setAge(12);
      complexObjectA.setSimpleObject(simpleObject);  
      /**
       * 使用BeanUtils.copyProperties 拷貝 模擬數(shù)據(jù) A 生成模擬數(shù)據(jù) B
       */
      ComplexObject complexObjectB=new ComplexObject();
      BeanUtils.copyProperties(complexObjectA,complexObjectB);

      System.out.println("拷貝后,查看模擬數(shù)據(jù)A 和 模擬數(shù)據(jù)B :");
      System.out.println(complexObjectA.getSimpleObject().toString());
      System.out.println(complexObjectB.getSimpleObject().toString());

      System.out.println("比較模擬數(shù)據(jù)A 和 模擬數(shù)據(jù)B 里面的引用對象simple 是否引用地址一樣: ");
      System.out.println(complexObjectA.getSimpleObject()==complexObjectB.getSimpleObject()); 

      System.out.println("修改拷貝出來的模擬數(shù)據(jù)B里面的引用對象simple的屬性 age 為 888888");
      complexObjectB.getSimpleObject().setAge(888888);

      System.out.println("修改后,觀察原數(shù)據(jù)A 和拷貝出來的數(shù)據(jù) B 里面引用的 對象 simple的屬性 age:");
      System.out.println(complexObjectA.getSimpleObject().toString());
      System.out.println(complexObjectB.getSimpleObject().toString()); 
  }

基于Beanutils.copyProperties()的用法及重寫提高效率

最后強調(diào)

如果你是使用BeanUtils.copyProperties 進行對象的拷貝復制, 一定要注意!

  • 第一點 、你所拷貝的對象內(nèi)包不包含 其他對象的引用。
  • 第二點、如果包含,那么接下來的方法里無論是操作原對象還是操作拷貝出來的對象是否涉及到 對 對象內(nèi) 的 那個其他對象的 值的修改 。
  • 第三點、如果涉及到, 修改了,會不會影響到其他方法 對 修改值的使用情況。

就如文中例子, 如果傳入過來的一個復雜對象數(shù)據(jù)A 里面引用了一個 user對象年齡age是10;拷貝出一份數(shù)據(jù)B后, 操作 數(shù)據(jù)B的方法把 年齡age改成了88888;

那么后續(xù)其他方法用到數(shù)據(jù)A ,想用的是最初始的 age 為10 ,那么就用不到了,因為淺拷貝的原因受影響,age都變成88888 了。

ok,就提到這。以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持服務器之家~

原文鏈接:https://blog.csdn.net/qq_37782076/article/details/86605282

延伸 · 閱讀

精彩推薦
  • Java教程Java實現(xiàn)搶紅包功能

    Java實現(xiàn)搶紅包功能

    這篇文章主要為大家詳細介紹了Java實現(xiàn)搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程xml與Java對象的轉(zhuǎn)換詳解

    xml與Java對象的轉(zhuǎn)換詳解

    這篇文章主要介紹了xml與Java對象的轉(zhuǎn)換詳解的相關(guān)資料,需要的朋友可以參考下...

    Java教程網(wǎng)2942020-09-17
  • Java教程Java BufferWriter寫文件寫不進去或缺失數(shù)據(jù)的解決

    Java BufferWriter寫文件寫不進去或缺失數(shù)據(jù)的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進去或缺失數(shù)據(jù)的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關(guān)于小米推送Java代碼,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩(wěn)中求8032021-07-12
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經(jīng)有好久沒有升過級了。升級完畢重啟之后,突然發(fā)現(xiàn)好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發(fā)現(xiàn)了對于集合操作轉(zhuǎn)換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關(guān)于Java8中S...

    阿杜7482021-02-04
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發(fā)項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
主站蜘蛛池模板: 美女视频黄a视频免费全过程 | 福利在线小视频 | 成年人视频免费 | 精品国产高清一区二区三区 | 91av在线免费观看 | av免费大全 | 国产美女做爰免费视 | 精品一区二区三区在线播放 | 亚洲四播房 | 在线中文字幕播放 | 国产日韩在线观看视频 | 九九视频精品在线观看 | 免费一级欧美在线观看视频 | 日本一区二区在线 | 日韩三区视频 | 蜜桃免费在线 | 国产成人在线网址 | 少妇一级淫片免费放4p | 精品一区二区三区毛片 | 日日操夜夜操狠狠操 | 最新视频一区二区 | 久久国产精品二区 | 草人人| 成人性生活视频在线播放 | 久久艹综合 | 久久成年人视频 | 婷婷中文字幕一区二区三区 | 九色com | 国产精品高潮视频 | 黄色二区三区 | 免费观看国产精品视频 | 一区二区三区四区高清视频 | 国产99久久精品一区二区300 | 欧美高清第一页 | 久久久久无码国产精品一区 | 羞羞网站入口 | 日韩一级免费 | 欧洲黄视频 | 爱操在线| 一级黄色性感片 | 国产毛片自拍 |