一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

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

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

服務器之家 - 編程語言 - Java教程 - BeanUtils.copyProperties復制不生效的解決

BeanUtils.copyProperties復制不生效的解決

2021-12-13 13:23藍風9 Java教程

這篇文章主要介紹了BeanUtils.copyProperties復制不生效的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

前言

呵呵 前端時間使用 BeanUtils.copyProperties 的時候碰到了一個這樣的問題

我有兩個實體, 有同樣的屬性, 一個有給定的屬性的 getter, 另外一個有 給定的屬性的 setter, 但是 我使用 BeanUtils.copyProperties 的時候 把來源對象的這個屬性 復制不到 目標對象上面

然后 當時也跟蹤了一下代碼, 然后 這里整理一下 改代碼片段吧

然后在調試的過程中 也發現了一些其他的問題, 呵呵 算是額外的了解吧

一下代碼基于 : jdk1.8.0_211 + commons-beanutils 1.9.4

 

問題的排查

首先來一段測試用例, 里面主要包含了三個類, 一個測試類, 兩個實體類

package com.hx.test03;  
import org.apache.commons.beanutils.BeanUtils; 
/**
* Test24BeanUtilsCopy
*
* @author Jerry.X.He <[email protected]>
* @version 1.0
* @date 2020-02-25 16:55
*/
public class Test24BeanUtilsCopy {

// Test24BeanUtilsCopy
// 1. 取的 source 的 propertyDescriptor
// 2. get, set 對應的類型不匹配
public static void main(String[] args) throws Exception {

  Test24ImmutableEntity fromImmutable = new Test24ImmutableEntity("fromImmutable");
  Test24MutableEntity fromMutable = new Test24MutableEntity("fromMutable");
  Test24MutableEntity targetEntity = new Test24MutableEntity("targetEntity");

  // does't work
  BeanUtils.copyProperties(targetEntity, fromImmutable);
  System.out.println(targetEntity.getAttr());
  // does't work
  BeanUtils.copyProperties(targetEntity, fromMutable);
  System.out.println(targetEntity.getAttr()); 
}
}
package com.hx.test03; 
/**
* ImmutablePayment
*
* @author Jerry.X.He <[email protected]>
* @version 1.0
* @date 2020-02-25 16:32
*/
public class Test24ImmutableEntity {

// attr
private final String attr;

public Test24ImmutableEntity(String attr) {
  this.attr = attr;
}

public String getAttr() {
  return attr;
} 
}
package com.hx.test03; 
import java.util.Optional; 
/**
* ImmutablePayment
*
* @author Jerry.X.He <[email protected]>
* @version 1.0
* @date 2020-02-25 16:32
*/
public class Test24MutableEntity {

// attr
private String attr;

public Test24MutableEntity(String attr) {
  this.attr = attr;
}

public Optional<String> getAttr() {
  return Optional.of(attr);
}

//  public String getAttr() {
//    return attr;
//  }

public void setAttr(String attr) {
  this.attr = attr;
} 
}

以上測試代碼輸出結果為 :

BeanUtils.copyProperties復制不生效的解決

從測試代碼中可以看到這里有兩個 BeanUtils.copyProperties 的使用, 并且兩個都沒有拷貝成功, 我們一個一個的來看

首先是第一個 BeanUtils.copyProperties, 來源對象 和 目標對象分別為 ImmutableEntity 和 MutableEntity

ImmutableEntity 上面有 getAttr, MutableEntity 上面有 setAttr, 但是為什么沒有拷貝成功呢 ?

在下圖的地方打一個斷點 調試一下

BeanUtils.copyProperties復制不生效的解決

調試發現 源對象是可讀的, 但是 目標對象不可寫?, 為什么呢?, 我們的 MutableEntity 不是有 setAttr 么

BeanUtils.copyProperties復制不生效的解決

在 processPropertyDescriptor 方法之后, 我們發現 attr 屬性, 居然不可寫了 ?

具體到 processPropertyDescriptor 方法, 他主要干的事情是

// 1. 尋找 getter(存在多個merge) 
// First pass. Find the latest getter method. Merge properties
// of previous getter methods.

// 2. 尋找 setter(存在多個merge) 
// Second pass. Find the latest setter method which
// has the same type as the getter method.

// 3. merge getter & setter 
// At this stage we should have either PDs or IPDs for the
// representative getters and setters. The order at which the
// property descriptors are determined represent the
// precedence of the property ordering.

以上注釋來自于 Introspector.java, 1, 2, 3 的注釋來自于我

我們這里重點關注 step2, 需要找到 類型匹配 getter 類型的 setter 方法, 但是我們這里的情況是 getter 返回值是 Optional, setter 返回值是 String, 因此類型不匹配 所以我們上面看到的結果是 有 getter, 沒得 setter

實際的上下文信息如下圖

BeanUtils.copyProperties復制不生效的解決

以上便是 第一個 BeanUtils.copyProperties 不生效的原因了

第二個 BeanUtils.copyProperties, 原因也是同上, 不過直觀的理解來說, attr 是有 getter 并且有 setter 的, 但是 由于規范的約定, 因此 propertyDescriptor 里面有 getter, 沒得 setter

 

問題的擴展

package com.hx.test03;  
import org.apache.commons.beanutils.BeanUtils; 
/**
* BeanUtilsCopy
*
* @author Jerry.X.He <[email protected]>
* @version 1.0
* @date 2020-02-24 12:49
*/
public class Test23BeanUtilsCopy {

// Test23BeanUtilsCopy
// 1. 取的 source 的 propertyDescriptor
// 2. get, set 對應的類型不匹配
public static void main(String[] args) throws Exception { 
  ImmutableEntity fromImmutable = new ImmutableEntity("fromImmutable");
  MutableEntity fromMutable = new MutableEntity("fromMutable");
  MutableEntity targetEntity = new MutableEntity("targetEntity");

  // does't work
  BeanUtils.copyProperties(targetEntity, fromImmutable);
  System.out.println(targetEntity.getAttr());
  // does't work
  BeanUtils.copyProperties(targetEntity, fromMutable);
  System.out.println(targetEntity.getAttr()); 
}
}

/**
* ImmutablePayment
*
* @author Jerry.X.He <[email protected]>
* @version 1.0
* @date 2020-02-24 12:50
*/
class ImmutableEntity {
// attr
private final String attr;

public ImmutableEntity(String attr) {
  this.attr = attr;
}

public String getAttr() {
  return attr;
}
}

/**
* MutablePayment
*
* @author Jerry.X.He <[email protected]>
* @version 1.0
* @date 2020-02-24 12:54
*/
class MutableEntity {
// attr
private String attr;

public MutableEntity(String attr) {
  this.attr = attr;
}

//  public Optional<String> getAttr() {
//    return Optional.of(attr);
//  }
public String getAttr() {
  return attr;
}

public void setAttr(String attr) {
  this.attr = attr;
}
}

我們吧如上代碼 整理到同一個文件中(這其實才是第一個 demo, 上文中的是第二個 demo), 并且調整了 MutableEntity.getter 使其和 setter 的類型能夠匹配

但是我們一跑, 發現結果還是有些出人意料

BeanUtils.copyProperties復制不生效的解決

BeanUtilsBean 如下地方打一個斷點

BeanUtils.copyProperties復制不生效的解決

我們發現這里有一個奇怪的現象, 源對象不可讀, 目標對象不可寫??, 這是怎么回事 ?

以 ImmutableEntity. getAttr 為例, 我們在 MethodUtils.getAccessableMethod 里面如下地方打一個斷點

BeanUtils.copyProperties復制不生效的解決

我們發現 尋找目標的方法主要有圖中 三個地方

第一個是當前類, 另外一個是當前類實現的接口, 另外一個是 當前類的基類(上圖還有未截取完的一部分, 限定 method 必須為 public, 否則不允許訪問)

  • 1. 在當前類查詢 : 首先需要限定當前類是 public(我們這里不滿足) public 允許訪問
  • 2. 當前類實現的接口查詢 : 獲取接口以及父接口中 匹配方法名字, 參數列表 的方法
  • 3. 當前類的基類查詢 : 獲取基類以及更上的基類中, 并且是 public 的基類, 匹配方法名字, 參數列表 的方法

因此, 我們這里的 第二個例子的 兩個 BeanUtils.copyProperties 也沒有生效

呵呵 不知道這個限定類為 public 的限定是否是 bug 呢?, 還是說 相關規范就是這么約定的呢 ?

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持服務器之家。

原文鏈接:https://jerryhe.blog.csdn.net/article/details/104500471

延伸 · 閱讀

精彩推薦
  • Java教程升級IDEA后Lombok不能使用的解決方法

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

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

    程序猿DD9332021-10-08
  • Java教程20個非常實用的Java程序代碼片段

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

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

    lijiao5352020-04-06
  • Java教程Java實現搶紅包功能

    Java實現搶紅包功能

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

    littleschemer13532021-05-16
  • Java教程Java8中Stream使用的一個注意事項

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

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

    阿杜7482021-02-04
  • Java教程xml與Java對象的轉換詳解

    xml與Java對象的轉換詳解

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

    Java教程網2942020-09-17
  • Java教程小米推送Java代碼

    小米推送Java代碼

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

    富貴穩中求8032021-07-12
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

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

    大行者10067412021-08-30
  • Java教程Java BufferWriter寫文件寫不進去或缺失數據的解決

    Java BufferWriter寫文件寫不進去或缺失數據的解決

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

    spcoder14552021-10-18
主站蜘蛛池模板: 特a级片 | 亚洲国产在线午夜视频无 | 精品亚洲综合久久中文字幕 | 青青99 | 19+韩国女主播激情vip视频在线 | 99欧美精品| 无限观看社区在线视频 | 草莓在深夜释放自己软件 | 午夜小视频免费 | 波多野结衣在线看 | 五月婷婷丁香在线视频 | 视频一区久久 | chinese帅男gayvideo| 韩国伦理hd | 日韩亚洲欧美一区二区三区 | 韩国久播影院理论片不卡影院 | 四虎现在的网址入口2022 | 精品日本一区二区 | 久9青青cao精品视频在线 | 色综合天天综合网国产人 | 99在线视频免费 | gaygayas男男免费中国 | 日韩伦理在线免费观看 | 国产中文在线视频 | jizz 日本亚洲 | 青草娱乐极品免费视频 | 91大神亚洲影视在线 | 亚洲同性男男gay1069 | 大学生按摩黄a级中文片 | 日韩大片在线播放 | 19+韩国女主播激情vip视频在线 | 国产一区二区不卡视频 | 女主被男主为催奶药h | 国产欧美日韩精品一区二 | 天天操天天舔 | 网红思瑞一区二区三区 | 日韩高清一区二区 | 欧美精品一区视频 | 欧美日韩亚洲综合在线一区二区 | 999精品视频这里只有精品 | 日韩一级精品视频在线观看 |