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

淺析Java中Apache BeanUtils和Spring BeanUtils的用法

 更新時(shí)間:2020年11月12日 16:07:46   作者:java夢想口服液  
這篇文章主要介紹了Java中Apache BeanUtils和Spring BeanUtils的用法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

# 前言

在我們實(shí)際項(xiàng)目開發(fā)過程中,我們經(jīng)常需要將不同的兩個(gè)對象實(shí)例進(jìn)行屬性復(fù)制,從而基于源對象的屬性信息進(jìn)行后續(xù)操作,而不改變源對象的屬性信息,比如DTO數(shù)據(jù)傳輸對象和數(shù)據(jù)對象DO,我們需要將DO對象進(jìn)行屬性復(fù)制到DTO,但是對象格式又不一樣,所以我們需要編寫映射代碼將對象中的屬性值從一種類型轉(zhuǎn)換成另一種類型。

# 對象拷貝

在具體介紹兩種 BeanUtils 之前,先來補(bǔ)充一些基礎(chǔ)知識。它們兩種工具本質(zhì)上就是對象拷貝工具,而對象拷貝又分為深拷貝和淺拷貝,下面進(jìn)行詳細(xì)解釋。

# 什么是淺拷貝和深拷貝

在Java中,除了 基本數(shù)據(jù)類型之外,還存在 類的實(shí)例對象這個(gè)引用數(shù)據(jù)類型,而一般使用 “=”號做賦值操作的時(shí)候,對于基本數(shù)據(jù)類型,實(shí)際上是拷貝的它的值,但是對于對象而言,其實(shí)賦值的只是這個(gè)對象的引用,將原對象的引用傳遞過去,他們實(shí)際還是指向的同一個(gè)對象。

而淺拷貝和深拷貝就是在這個(gè)基礎(chǔ)上做的區(qū)分,如果在拷貝這個(gè)對象的時(shí)候,只對基本數(shù)據(jù)類型進(jìn)行了拷貝,而對引用數(shù)據(jù)類型只是進(jìn)行引用的傳遞,而沒有真實(shí)的創(chuàng)建一個(gè)新的對象,則認(rèn)為是淺拷貝。反之,在對引用數(shù)據(jù)類型進(jìn)行拷貝的時(shí)候,創(chuàng)建了一個(gè)新的對象,并且復(fù)制其內(nèi)的成員變量,則認(rèn)為是深拷貝。

簡單來說:

淺拷貝:對基本數(shù)據(jù)類型進(jìn)行值傳遞,對引用數(shù)據(jù)類型進(jìn)行引用傳遞般的拷貝,此為淺拷貝

深拷貝:對基本數(shù)據(jù)類型進(jìn)行值傳遞,對引用數(shù)據(jù)類型,創(chuàng)建一個(gè)新的對象,并復(fù)制其內(nèi)容,此為深拷貝。

兩難!到底用Apache BeanUtils還是Spring BeanUtils?

# BeanUtils

前面簡單講了一下對象拷貝的一些知識,下面就來具體看下兩種 BeanUtils 工具

# Apache 的 BeanUtils

首先來看一個(gè)非常簡單的BeanUtils的例子

publicclass PersonSource {
 private Integer id;
 private String username;
 private String password;
 private Integer age;
 // getters/setters omiited
}
publicclass PersonDest {
 private Integer id;
 private String username;
 private Integer age;
 // getters/setters omiited
}
publicclass TestApacheBeanUtils {
 public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
  //下面只是用于單獨(dú)測試
  PersonSource personSource = new PersonSource(1, "pjmike", "12345", 21);
  PersonDest personDest = new PersonDest();
  BeanUtils.copyProperties(personDest,personSource);
  System.out.println("persondest: "+personDest);
 }
}
persondest: PersonDest{id=1, username='pjmike', age=21}

從上面的例子可以看出,對象拷貝非常簡單,BeanUtils最常用的方法就是:

//將源對象中的值拷貝到目標(biāo)對象//將源對象中的值拷貝到目標(biāo)對象
public static void copyProperties(Object dest, Object orig) throws IllegalAccessException, InvocationTargetException {
 BeanUtilsBean.getInstance().copyProperties(dest, orig);
}

但是由于 Apache下的BeanUtils對象拷貝性能太差,不建議使用,而且在阿里巴巴Java開發(fā)規(guī)約插件上也明確指出:

Ali-Check | 避免用Apache Beanutils進(jìn)行屬性的copy。

commons-beantutils 對于對象拷貝加了很多的檢驗(yàn),包括類型的轉(zhuǎn)換,甚至還會檢驗(yàn)對象所屬的類的可訪問性,可謂相當(dāng)復(fù)雜,這也造就了它的差勁的性能,具體實(shí)現(xiàn)代碼如下:

public void copyProperties(final Object dest, final Object orig)
  throws IllegalAccessException, InvocationTargetException {

  // Validate existence of the specified beans
  if (dest == null) {
   thrownew IllegalArgumentException
     ("No destination bean specified");
  }
  if (orig == null) {
   thrownew IllegalArgumentException("No origin bean specified");
  }
  if (log.isDebugEnabled()) {
   log.debug("BeanUtils.copyProperties(" + dest + ", " +
      orig + ")");
  }

  // Copy the properties, converting as necessary
  if (orig instanceof DynaBean) {
   final DynaProperty[] origDescriptors =
    ((DynaBean) orig).getDynaClass().getDynaProperties();
   for (DynaProperty origDescriptor : origDescriptors) {
    final String name = origDescriptor.getName();
    // Need to check isReadable() for WrapDynaBean
    // (see Jira issue# BEANUTILS-61)
    if (getPropertyUtils().isReadable(orig, name) &&
     getPropertyUtils().isWriteable(dest, name)) {
     final Object value = ((DynaBean) orig).get(name);
     copyProperty(dest, name, value);
    }
   }
  } elseif (orig instanceof Map) {
   @SuppressWarnings("unchecked")
   final
   // Map properties are always of type <String, Object>
   Map<String, Object> propMap = (Map<String, Object>) orig;
   for (final Map.Entry<String, Object> entry : propMap.entrySet()) {
    final String name = entry.getKey();
    if (getPropertyUtils().isWriteable(dest, name)) {
     copyProperty(dest, name, entry.getValue());
    }
   }
  } else/* if (orig is a standard JavaBean) */ {
   final PropertyDescriptor[] origDescriptors =
    getPropertyUtils().getPropertyDescriptors(orig);
   for (PropertyDescriptor origDescriptor : origDescriptors) {
    final String name = origDescriptor.getName();
    if ("class".equals(name)) {
     continue; // No point in trying to set an object's class
    }
    if (getPropertyUtils().isReadable(orig, name) &&
     getPropertyUtils().isWriteable(dest, name)) {
     try {
      final Object value =
       getPropertyUtils().getSimpleProperty(orig, name);
      copyProperty(dest, name, value);
     } catch (final NoSuchMethodException e) {
      // Should not happen
     }
    }
   }
  }

 }

# Spring 的 BeanUtils

使用spring的BeanUtils進(jìn)行對象拷貝:

publicclass TestSpringBeanUtils {
 public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {

  //下面只是用于單獨(dú)測試
  PersonSource personSource = new PersonSource(1, "pjmike", "12345", 21);
  PersonDest personDest = new PersonDest();
  BeanUtils.copyProperties(personSource,personDest);
  System.out.println("persondest: "+personDest);
 }
}

Spring下的BeanUtils也是使用 copyProperties方法進(jìn)行拷貝,只不過它的實(shí)現(xiàn)方式非常簡單,就是對兩個(gè)對象中相同名字的屬性進(jìn)行簡單的get/set,僅檢查屬性的可訪問性。具體實(shí)現(xiàn)如下:

private static void copyProperties(Object source, Object target, @Nullable Class<?> editable,
  @Nullable String... ignoreProperties) throws BeansException {

 Assert.notNull(source, "Source must not be null");
 Assert.notNull(target, "Target must not be null");

 Class<?> actualEditable = target.getClass();
 if (editable != null) {
  if (!editable.isInstance(target)) {
  throw new IllegalArgumentException("Target class [" + target.getClass().getName() +
   "] not assignable to Editable class [" + editable.getName() + "]");
  }
  actualEditable = editable;
 }
 PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
 List<String> ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null);

 for (PropertyDescriptor targetPd : targetPds) {
  Method writeMethod = targetPd.getWriteMethod();
  if (writeMethod != null && (ignoreList == null || !ignoreList.contains(targetPd.getName()))) {
  PropertyDescriptor sourcePd = getPropertyDescriptor(source.getClass(), targetPd.getName());
  if (sourcePd != null) {
   Method readMethod = sourcePd.getReadMethod();
   if (readMethod != null &&
    ClassUtils.isAssignable(writeMethod.getParameterTypes()[0], readMethod.getReturnType())) {
   try {
    if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
    readMethod.setAccessible(true);
    }
    Object value = readMethod.invoke(source);
    if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
    writeMethod.setAccessible(true);
    }
    writeMethod.invoke(target, value);
   }
   catch (Throwable ex) {
    throw new FatalBeanException(
     "Could not copy property '" + targetPd.getName() + "' from source to target", ex);
   }
   }
  }
  }
 }
 }

可以看到,成員變量賦值是基于目標(biāo)對象的成員列表,并且會跳過ignore的以及在源對象中不存在,所以這個(gè)方法是安全的,不會因?yàn)閮蓚€(gè)對象之間的結(jié)構(gòu)差異導(dǎo)致錯誤,但是必須保證同名的兩個(gè)成員變量類型相同

# 小結(jié)

以上簡要的分析兩種BeanUtils,因?yàn)锳pache下的BeanUtils性能較差,不建議使用,可以使用 Spring的BeanUtils ,或者使用其他拷貝框架,比如:Dozer、ModelMapper等等

到此這篇關(guān)于淺析Java中Apache BeanUtils和Spring BeanUtils的用法的文章就介紹到這了,更多相關(guān)Apache BeanUtils和Spring BeanUtils內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Maven項(xiàng)目部署到服務(wù)器設(shè)置訪問路徑以及配置虛擬目錄的方法

    Maven項(xiàng)目部署到服務(wù)器設(shè)置訪問路徑以及配置虛擬目錄的方法

    今天小編就為大家分享一篇關(guān)于Maven項(xiàng)目部署到服務(wù)器設(shè)置訪問路徑以及配置虛擬目錄的方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • Java中泛型的示例詳解

    Java中泛型的示例詳解

    泛型機(jī)制在項(xiàng)目中一直都在使用,不僅如此,很多源碼中都用到了泛型機(jī)制。本文將通過一些示例帶大家深入了解一下Java的泛型機(jī)制,需要的可以了解一下
    2022-10-10
  • Java中的cglib代理詳解

    Java中的cglib代理詳解

    這篇文章主要介紹了Java中的cglib代理詳解, 代理模式是一種設(shè)計(jì)模式,它可以為其他對象提供一種代理,以控制對該對象的訪問,可以在運(yùn)行時(shí)動態(tài)地創(chuàng)建代理對象,而不需要手動編寫代理類的代碼,需要的朋友可以參考下
    2023-09-09
  • Intellij IDEA實(shí)現(xiàn)SpringBoot項(xiàng)目多端口啟動的兩種方法

    Intellij IDEA實(shí)現(xiàn)SpringBoot項(xiàng)目多端口啟動的兩種方法

    有時(shí)候使用springboot項(xiàng)目時(shí)遇到這樣一種情況,用一個(gè)項(xiàng)目需要復(fù)制很多遍進(jìn)行測試,除了端口號不同以外,沒有任何不同。遇到這種情況怎么辦呢?這時(shí)候可以使用Intellij IDEA解決
    2018-06-06
  • IDEA找不到j(luò)dk該如何解決

    IDEA找不到j(luò)dk該如何解決

    這篇文章主要給大家介紹了關(guān)于IDEA找不到j(luò)dk該如何解決的相關(guān)資料,剛安裝好IDEA后,我們運(yùn)行一個(gè)項(xiàng)目時(shí)候,有時(shí)候會遇到顯示找不到Java的JDK,需要的朋友可以參考下
    2023-11-11
  • java開發(fā)ServiceLoader實(shí)現(xiàn)機(jī)制及SPI應(yīng)用

    java開發(fā)ServiceLoader實(shí)現(xiàn)機(jī)制及SPI應(yīng)用

    這篇文章主要為大家介紹了java開發(fā)ServiceLoader實(shí)現(xiàn)機(jī)制及SPI應(yīng)用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-10-10
  • idea中創(chuàng)建多module的maven工程的方法

    idea中創(chuàng)建多module的maven工程的方法

    這篇文章主要介紹了idea中創(chuàng)建多module的maven工程的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-10-10
  • 示例解析java面向?qū)ο缶幊谭庋b與訪問控制

    示例解析java面向?qū)ο缶幊谭庋b與訪問控制

    這篇文章主要為大家介紹了java封裝與訪問控制的示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • SpringBoot整合Redis及Redis工具類撰寫實(shí)例

    SpringBoot整合Redis及Redis工具類撰寫實(shí)例

    這篇文章主要介紹了SpringBoot整合Redis及Redis工具類撰寫實(shí)例,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-01-01
  • 詳解springboot整合ueditor踩過的坑

    詳解springboot整合ueditor踩過的坑

    這篇文章主要介紹了詳解springboot整合ueditor踩過的坑,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06

最新評論

永仁县| 台安县| 怀安县| 合作市| 长子县| 阳春市| 石河子市| 铜鼓县| 宕昌县| 通辽市| 冀州市| 辽阳县| 海安县| 溧水县| 桂平市| 衡南县| 保山市| 海口市| 耒阳市| 南岸区| 武宁县| 顺昌县| 饶河县| 广元市| 双辽市| 连山| 家居| 临夏县| 治县。| 德格县| 商都县| 冀州市| 罗田县| 霍邱县| 青冈县| 雅安市| 阿拉善左旗| 平凉市| 慈溪市| 曲靖市| 邢台市|