最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

BeanUtils.copyProperties復(fù)制不生效的解決

 更新時(shí)間:2021年09月01日 09:45:30   作者:藍(lán)風(fēng)9  
這篇文章主要介紹了BeanUtils.copyProperties復(fù)制不生效的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

前言

呵呵 前端時(shí)間使用 BeanUtils.copyProperties 的時(shí)候碰到了一個(gè)這樣的問(wèn)題

我有兩個(gè)實(shí)體, 有同樣的屬性, 一個(gè)有給定的屬性的 getter, 另外一個(gè)有 給定的屬性的 setter, 但是 我使用 BeanUtils.copyProperties 的時(shí)候 把來(lái)源對(duì)象的這個(gè)屬性 復(fù)制不到 目標(biāo)對(duì)象上面

然后 當(dāng)時(shí)也跟蹤了一下代碼, 然后 這里整理一下 改代碼片段吧

然后在調(diào)試的過(guò)程中 也發(fā)現(xiàn)了一些其他的問(wèn)題, 呵呵 算是額外的了解吧

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

問(wèn)題的排查

首先來(lái)一段測(cè)試用例, 里面主要包含了三個(gè)類(lèi), 一個(gè)測(cè)試類(lèi), 兩個(gè)實(shí)體類(lèi)

package com.hx.test03;  
import org.apache.commons.beanutils.BeanUtils; 
/**
 * Test24BeanUtilsCopy
 *
 * @author Jerry.X.He <970655147@qq.com>
 * @version 1.0
 * @date 2020-02-25 16:55
 */
public class Test24BeanUtilsCopy {
 
  // Test24BeanUtilsCopy
  // 1. 取的 source 的 propertyDescriptor
  // 2. get, set 對(duì)應(yīng)的類(lèi)型不匹配
  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 <970655147@qq.com>
 * @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 <970655147@qq.com>
 * @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;
  } 
}

以上測(cè)試代碼輸出結(jié)果為 :

從測(cè)試代碼中可以看到這里有兩個(gè) BeanUtils.copyProperties 的使用, 并且兩個(gè)都沒(méi)有拷貝成功, 我們一個(gè)一個(gè)的來(lái)看

首先是第一個(gè) BeanUtils.copyProperties, 來(lái)源對(duì)象 和 目標(biāo)對(duì)象分別為 ImmutableEntity 和 MutableEntity

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

在下圖的地方打一個(gè)斷點(diǎn) 調(diào)試一下

調(diào)試發(fā)現(xiàn) 源對(duì)象是可讀的, 但是 目標(biāo)對(duì)象不可寫(xiě)?, 為什么呢?, 我們的 MutableEntity 不是有 setAttr 么

在 processPropertyDescriptor 方法之后, 我們發(fā)現(xiàn) attr 屬性, 居然不可寫(xiě)了 ?

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

// 1. 尋找 getter(存在多個(gè)merge) 
// First pass. Find the latest getter method. Merge properties
// of previous getter methods.
 
// 2. 尋找 setter(存在多個(gè)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.

以上注釋來(lái)自于 Introspector.java, 1, 2, 3 的注釋來(lái)自于我

我們這里重點(diǎn)關(guān)注 step2, 需要找到 類(lèi)型匹配 getter 類(lèi)型的 setter 方法, 但是我們這里的情況是 getter 返回值是 Optional, setter 返回值是 String, 因此類(lèi)型不匹配 所以我們上面看到的結(jié)果是 有 getter, 沒(méi)得 setter

實(shí)際的上下文信息如下圖

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

第二個(gè) BeanUtils.copyProperties, 原因也是同上, 不過(guò)直觀的理解來(lái)說(shuō), attr 是有 getter 并且有 setter 的, 但是 由于規(guī)范的約定, 因此 propertyDescriptor 里面有 getter, 沒(méi)得 setter

問(wèn)題的擴(kuò)展

package com.hx.test03;  
import org.apache.commons.beanutils.BeanUtils; 
/**
 * BeanUtilsCopy
 *
 * @author Jerry.X.He <970655147@qq.com>
 * @version 1.0
 * @date 2020-02-24 12:49
 */
public class Test23BeanUtilsCopy {
 
  // Test23BeanUtilsCopy
  // 1. 取的 source 的 propertyDescriptor
  // 2. get, set 對(duì)應(yīng)的類(lèi)型不匹配
  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 <970655147@qq.com>
 * @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 <970655147@qq.com>
 * @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;
  }
}
 

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

但是我們一跑, 發(fā)現(xiàn)結(jié)果還是有些出人意料

BeanUtilsBean 如下地方打一個(gè)斷點(diǎn)

我們發(fā)現(xiàn)這里有一個(gè)奇怪的現(xiàn)象, 源對(duì)象不可讀, 目標(biāo)對(duì)象不可寫(xiě)??, 這是怎么回事 ?

以 ImmutableEntity. getAttr 為例, 我們?cè)?MethodUtils.getAccessableMethod 里面如下地方打一個(gè)斷點(diǎn)

我們發(fā)現(xiàn) 尋找目標(biāo)的方法主要有圖中 三個(gè)地方

第一個(gè)是當(dāng)前類(lèi), 另外一個(gè)是當(dāng)前類(lèi)實(shí)現(xiàn)的接口, 另外一個(gè)是 當(dāng)前類(lèi)的基類(lèi)(上圖還有未截取完的一部分, 限定 method 必須為 public, 否則不允許訪問(wèn))

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

因此, 我們這里的 第二個(gè)例子的 兩個(gè) BeanUtils.copyProperties 也沒(méi)有生效

呵呵 不知道這個(gè)限定類(lèi)為 public 的限定是否是 bug 呢?, 還是說(shuō) 相關(guān)規(guī)范就是這么約定的呢 ?

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java制作廣告圖片自動(dòng)輪播控件

    java制作廣告圖片自動(dòng)輪播控件

    本文給大家分享了2款java實(shí)現(xiàn)的首頁(yè)廣告圖片自動(dòng)輪播的控件,分別是PC端和移動(dòng)端的,效果非常不錯(cuò),有需要的小伙伴可以參考下。
    2015-10-10
  • Java對(duì)Map進(jìn)行按value排序的幾種常見(jiàn)方法

    Java對(duì)Map進(jìn)行按value排序的幾種常見(jiàn)方法

    在日常開(kāi)發(fā)中,Map 是我們經(jīng)常使用的數(shù)據(jù)結(jié)構(gòu)之一,盡管 Map 是按鍵 (key) 存儲(chǔ)和檢索數(shù)據(jù)的,但有時(shí)我們需要根據(jù) value 進(jìn)行排序,這篇博客將詳細(xì)探討如何在 Java 中對(duì) Map 進(jìn)行按 value 排序的幾種常見(jiàn)方法,并分析它們的優(yōu)缺點(diǎn),需要的朋友可以參考下
    2025-03-03
  • 深入理解Java 線程通信

    深入理解Java 線程通信

    這篇文章主要介紹了Java 線程通信的的相關(guān)資料,文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下
    2020-06-06
  • Java序列化(Serialization) 機(jī)制

    Java序列化(Serialization) 機(jī)制

    本篇文章是對(duì)Java中對(duì)象的序列化(Serialization) 機(jī)制進(jìn)行了詳細(xì)的分析介紹,并附實(shí)例,需要的朋友可以參考下
    2016-07-07
  • IntelliJ?IDEA2022.3?springboot?熱部署含靜態(tài)文件(最新推薦)

    IntelliJ?IDEA2022.3?springboot?熱部署含靜態(tài)文件(最新推薦)

    這篇文章主要介紹了IntelliJ?IDEA2022.3?springboot?熱部署含靜態(tài)文件,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-01-01
  • idea在工具欄中顯示快速創(chuàng)建包和類(lèi)的圖標(biāo)的詳細(xì)步驟

    idea在工具欄中顯示快速創(chuàng)建包和類(lèi)的圖標(biāo)的詳細(xì)步驟

    點(diǎn)擊需要?jiǎng)?chuàng)建包或者類(lèi)的位置,在點(diǎn)擊對(duì)用的圖標(biāo)就可以快速創(chuàng)建類(lèi)或者包了,下面小編給大家介紹idea在工具欄中顯示快速創(chuàng)建包和類(lèi)的圖標(biāo)的詳細(xì)步驟,感興趣的朋友一起看看吧
    2024-02-02
  • springboot aop添加日志方式

    springboot aop添加日志方式

    這篇文章主要介紹了springboot aop添加日志方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-05-05
  • Springboot如何配置多個(gè)Redis數(shù)據(jù)源(非集群)

    Springboot如何配置多個(gè)Redis數(shù)據(jù)源(非集群)

    這篇文章主要介紹了Springboot如何配置多個(gè)Redis數(shù)據(jù)源(非集群)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • Java GUI編程實(shí)現(xiàn)在線聊天室

    Java GUI編程實(shí)現(xiàn)在線聊天室

    這篇文章主要為大家詳細(xì)介紹了Java GUI編程實(shí)現(xiàn)在線聊天室,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-07-07
  • 詳解Java8中的lambda表達(dá)式、::符號(hào)和Optional類(lèi)

    詳解Java8中的lambda表達(dá)式、::符號(hào)和Optional類(lèi)

    這篇文章主要介紹了Java8中的lambda表達(dá)式、::符號(hào)和Optional類(lèi),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04

最新評(píng)論

临猗县| 石门县| 封丘县| 英吉沙县| 甘肃省| 丹巴县| 泰安市| 清徐县| 延吉市| 蒲江县| 临武县| 沙坪坝区| 惠来县| 平定县| 湛江市| 黑河市| 宿松县| 新余市| 宿松县| 文水县| 永登县| 西畴县| 色达县| 英山县| 北宁市| 贡觉县| 长宁县| 泰州市| 纳雍县| 文成县| 伽师县| 扎兰屯市| 金堂县| 鄂尔多斯市| 阜康市| 自贡市| 滕州市| 广元市| 襄樊市| 河西区| 咸丰县|