摘要:拷貝操作又一個非常好用的工具類和中分別存在一個,提供了對。除了支持基本類型以及基本類型的數組之外,還支持這些類的對象,其余一概不支持。而且,由于這些類都是采用反射機制實現的,對程序的效率也會有影響。因此,慎用或者使用看效果如何
java bean拷貝操作又一個非常好用的工具類 BeanUitls :
spring (org.springframework.beans.BeanUtils)和apache commons-beanutils(org.apache.commons.beanutils.BeanUtils)中分別存在一個BeanUtils,提供了對。
特別注意 這兩個類在不同的包下面,而這兩個類的copyProperties()方法里面傳遞的參數賦值是相反的。
例如:
a,b為對象
BeanUtils.copyProperties(a, b);
BeanUtils是org.springframework.beans.BeanUtils,
a拷貝到b
BeanUtils是org.apache.commons.beanutils.BeanUtils,
b拷貝到a
之前在寫程序時,用到了兩個不同類型但屬性基本相同的對象的拷貝,由于類型不同源bean里屬性(Integer 向 int 拷貝)其值為null,這時會拋異常。
/** * 測試 spring 中的 bean 拷貝 * @throws Exception */ @org.junit.Test public void testBeanCopy() throws Exception { PersonEntity pe = new PersonEntity(); pe.setAge(1); //pe.setId(1234); // id 為 Integer 此時為null pe.setName("kevin"); Person person = new Person(); // Person 中的id為int類型 BeanUtils.copyProperties(pe, person); System.out.println(person); }
一個看似簡單的問題困擾了在當時,于是抽空看了一下spring和apache commons-beanutils包中BeanUtils.copyProperties的實現。
spring中實現的方式很簡單,就是對兩個對象中相同名字的屬性進行簡單get/set,僅檢查屬性的可訪問性。
源碼
package org.springframework.beans; private static void copyProperties(Object source, Object target, Class> editable, 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); ListignoreList = (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); } } } } } }
而commons-beanutils則施加了很多的檢驗,包括類型的轉換,甚至于還會檢驗對象所屬的類的可訪問性。
源碼
package org.apache.commons.beanutils; public void copyProperties(Object dest, Object orig) throws IllegalAccessException, InvocationTargetException { // Validate existence of the specified beans if (dest == null) { throw new IllegalArgumentException ("No destination bean specified"); } if (orig == null) { throw new IllegalArgumentException("No origin bean specified"); } if (log.isDebugEnabled()) { log.debug("BeanUtils.copyProperties(" + dest + ", " + orig + ")"); } // Copy the properties, converting as necessary if (orig instanceof DynaBean) { DynaProperty origDescriptors[] = ((DynaBean) orig).getDynaClass().getDynaProperties(); for (int i = 0; i < origDescriptors.length; i++) { String name = origDescriptors[i].getName(); if (getPropertyUtils().isWriteable(dest, name)) { Object value = ((DynaBean) orig).get(name); copyProperty(dest, name, value); } } } else if (orig instanceof Map) { Iterator names = ((Map) orig).keySet().iterator(); while (names.hasNext()) { String name = (String) names.next(); if (getPropertyUtils().isWriteable(dest, name)) { Object value = ((Map) orig).get(name); copyProperty(dest, name, value); } } } else /* if (orig is a standard JavaBean) */ { PropertyDescriptor origDescriptors[] = getPropertyUtils().getPropertyDescriptors(orig); for (int i = 0; i < origDescriptors.length; i++) { String name = origDescriptors[i].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 { Object value = getPropertyUtils().getSimpleProperty(orig, name); copyProperty(dest, name, value); } catch (NoSuchMethodException e) { ; // Should not happen } } } } }
而且,commons-beanutils中的裝換是不支持java.util.Date的。除了支持基本類型以及基本類型的數組之外,還支持java.sql.Date, java.sql.Time, java.sql.TimeStamp, java.io.File, javaio.URL這些類的對象,其余一概不支持。不過你可以自定義你的類的Converter。然后注冊進去。所以在使用時
感覺commons-beanutils包中的這個BeanUtils類的copyProperties方法,太過復雜,約束太多,而且使用不便,雖然可擴展性好了,但是易用性不高。
總結:
關于bean復制,如果屬性較少,建議直接寫個方法完成get/set即可。如果屬性較多,可以自己采用反射實現一個滿足自己需要的工具類,或者使用spring的那個beanutils類,不建議使用commons-beanutils包中的那個BeanUtils類,剛看了下,這個類對于內部靜態類的對象復制也會出現問題,檢驗太復雜了,常會出現一些詭異的問題。畢竟我們bean復制一般就是簡單的屬性copy而已。
而且,由于這些BeanUtils類都是采用反射機制實現的,對程序的效率也會有影響。因此,慎用BeanUtils.copyProperties?。?!或者使用clone看效果如何!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/35799.html
摘要:從而能夠進一步深入了解框架。至此我們框架開發完成。雖然說閱讀源碼是了解框架的最終手段。但是框架作為一個生產框架,為了保證通用和穩定,源碼必定是高度抽象,且處理大量細節。下一篇文章應該會是徒手擼框架實現。 原文地址:https://www.xilidou.com/2018/... Spring 作為 J2ee 開發事實上的標準,是每個Java開發人員都需要了解的框架。但是Spring 的...
1. BeanUtils.copyProperties(Object source, Object target) 用法: 講source的屬性值復制到target,屬性為null時也會進行復制。 需求:排除null值進行復制 public class CopyObjectUtil { public static String[] getNullPropertyNames(Object...
摘要:于是我建議這位小伙伴使用了進行屬性拷貝,這為我們的程序挖了一個坑阿里代碼規約當我們開啟阿里代碼掃描插件時,如果你使用了進行屬性拷貝,它會給你一個非常嚴重的警告。大名鼎鼎的提供的包,居然會存在性能問題,以致于阿里給出了嚴重的警告。 聲明:本文屬原創文章,始發于公號:程序員自學之道,并同步發布于 https://blog.csdn.net/dadiyang,特此,同步發布到 sf,轉載請注...
摘要:解決鏈路間參數傳遞的問題可以簡化為解決接口間的參數傳遞問題。當然,針對這個問題的解決方案,其實還是蠻多的??偨Y下來,自動化用例的維護和開發成本主要集中在接口間參數傳遞的維護上面。 引言 做過接口自動化測試的同學肯定都熟悉在全鏈路測試過程中,很多業務場景的完成并非由單一接口實現,而是由很多接...
摘要:背景許多時候需要對比不同的框架或工具或算法,選擇使用性能更優的那一個。通常的做法是但這樣的做法非常不嚴謹,因為當獨立頻繁運行這一小塊代碼時,可能會針對性的做一些優化工作,而在實際的生產環境中是不會有此優化的。 背景 許多時候需要對比不同的框架或工具或算法, 選擇使用性能更優的那一個。通常的做法是 long start = System.currentTimeMillis(); for(...
閱讀 2852·2023-04-25 17:59
閱讀 682·2023-04-25 15:05
閱讀 673·2021-11-25 09:43
閱讀 3034·2021-10-12 10:13
閱讀 3537·2021-09-27 13:59
閱讀 3583·2021-09-23 11:21
閱讀 3879·2021-09-08 09:35
閱讀 564·2019-08-29 17:12