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

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

 更新時(shí)間:2021年09月01日 09:21:06   作者:菜鳥凱一枚  
這篇文章主要介紹了Beanutils.copyProperties( )的用法及重寫提高效率的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

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。

一、簡(jiǎn)介

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

二、用法

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

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

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

不愿意這樣做。

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

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

注:如果User和UserActionForm 間存在名稱不相同的屬性,則BeanUtils不對(duì)這些屬性進(jìn)行處理,需要手動(dòng)處理。例如:

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

user.setModifyDate(new Date());  

三、重寫

ReflectASM,高性能的反射:

什么是ReflectASM ReflectASM是一個(gè)很小的java類庫,主要是通過asm生產(chǎn)類來實(shí)現(xiàn)java反射,執(zhí)行速度非常快,看了網(wǎng)上很多和反射的對(duì)比,覺得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);    
    }    

原理

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

看了下源碼,這段代碼主要是通過asm生產(chǎn)一個(gè)User的處理類 UserMethodAccess(這個(gè)類主要是實(shí)現(xiàn)了invoke方法)的ByteCode,然后獲得該對(duì)象,通過上面的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ù)一需要反射的對(duì)象  
                // 參數(shù)二class.getDeclaredMethods 對(duì)應(yīng)方法的index  
                // 參數(shù)對(duì)三象集合  
                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方法的下標(biāo)  
                    int setIndex = methodAccess.getIndex("set" + fieldName); // 獲取set方法的下標(biāo)  
                    methodIndexMap.put(orgi.getClass().getName() + "." + "get"  
                            + fieldName, getIndex); // 將類名get方法名,方法下標(biāo)注冊(cè)到map中  
                    methodIndexMap.put(orgi.getClass().getName() + "." + "set"  
                            + fieldName, setIndex); // 將類名set方法名,方法下標(biāo)注冊(cè)到map中  
                    fieldList.add(fieldName); // 將屬性名稱放入集合里  
                }  
            }  
            fieldMap.put(orgi.getClass(), fieldList); // 將類名,屬性名稱注冊(cè)到map中  
            methodMap.put(orgi.getClass(), methodAccess);  
            return methodAccess;  
        }  
    } 

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

BeanUtils.copyProperties 使用注意

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

為什么今天我還想把這個(gè)BeanUtils.copyProperties 的使用拿出來軍訓(xùn)。

因?yàn)槲乙庾R(shí)到了大家(部分)對(duì)深拷淺拷還是不清晰,不知道具體的影響。

示例演示

第一個(gè)類:

第二個(gè)類:

注意!! 第二個(gè)類里面有使用第一個(gè)類。

開始進(jìn)行示例

    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 里面的引用對(duì)象simple 是否引用地址一樣: ");
        System.out.println(complexObjectA.getSimpleObject()==complexObjectB.getSimpleObject()); 
 
        System.out.println("修改拷貝出來的模擬數(shù)據(jù)B里面的引用對(duì)象simple的屬性 age 為 888888");
        complexObjectB.getSimpleObject().setAge(888888);
 
        System.out.println("修改后,觀察原數(shù)據(jù)A 和拷貝出來的數(shù)據(jù) B 里面引用的 對(duì)象 simple的屬性 age:");
        System.out.println(complexObjectA.getSimpleObject().toString());
        System.out.println(complexObjectB.getSimpleObject().toString()); 
    }

最后強(qiáng)調(diào)

如果你是使用BeanUtils.copyProperties 進(jìn)行對(duì)象的拷貝復(fù)制, 一定要注意!

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

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

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

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

相關(guān)文章

  • java中concat()方法的使用說明

    java中concat()方法的使用說明

    這篇文章主要介紹了java中concat()方法的使用說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • java連接mongoDB并進(jìn)行增刪改查操作實(shí)例詳解

    java連接mongoDB并進(jìn)行增刪改查操作實(shí)例詳解

    這篇文章主要介紹了java連接mongoDB并進(jìn)行增刪改查操作,結(jié)合實(shí)例形式詳細(xì)分析了java環(huán)境下MongoDB擴(kuò)展包的下載、安裝及操作MongoDB連接、增刪改查等相關(guān)操作技巧,需要的朋友可以參考下
    2019-04-04
  • SpringBoot中@EnableAutoConfiguration和@Configuration的區(qū)別

    SpringBoot中@EnableAutoConfiguration和@Configuration的區(qū)別

    這篇文章主要介紹了SpringBoot中@EnableAutoConfiguration和@Configuration的區(qū)別,@SpringBootApplication相當(dāng)于@EnableAutoConfiguration,@ComponentScan,@Configuration三者的集合,需要的朋友可以參考下
    2023-08-08
  • Java用freemarker導(dǎo)出word實(shí)用示例

    Java用freemarker導(dǎo)出word實(shí)用示例

    本篇文章主要介紹了Java用freemarker導(dǎo)出word實(shí)用示例,使用freemarker的模板來實(shí)現(xiàn)功能,有需要的可以了解一下。
    2016-11-11
  • Java?六類運(yùn)算符詳解

    Java?六類運(yùn)算符詳解

    這篇文章主要介紹了Java?六類運(yùn)算符,在?Java?語言中,運(yùn)算符有算數(shù)運(yùn)算符、關(guān)系運(yùn)算符、邏輯運(yùn)算符、賦值運(yùn)算符、字符串連接運(yùn)算符、條件運(yùn)算符,感興趣的朋友可以閱讀一下
    2023-03-03
  • SpringMVC使用注解實(shí)現(xiàn)登錄功能

    SpringMVC使用注解實(shí)現(xiàn)登錄功能

    這篇文章主要為大家詳細(xì)介紹了SpringMVC使用注解實(shí)現(xiàn)登錄功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-09-09
  • SpringMVC框架實(shí)現(xiàn)上傳圖片的示例代碼

    SpringMVC框架實(shí)現(xiàn)上傳圖片的示例代碼

    本篇文章主要介紹了SpringMVC框架實(shí)現(xiàn)上傳圖片的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-09-09
  • Java BigInteger類,BigDecimal類,Date類,DateFormat類及Calendar類用法示例

    Java BigInteger類,BigDecimal類,Date類,DateFormat類及Calendar類用法示例

    這篇文章主要介紹了Java BigInteger類,BigDecimal類,Date類,DateFormat類及Calendar類用法,結(jié)合實(shí)例形式詳細(xì)分析了Java使用BigInteger類,BigDecimal類,Date類,DateFormat類及Calendar類進(jìn)行數(shù)值運(yùn)算與日期運(yùn)算相關(guān)操作技巧,需要的朋友可以參考下
    2019-03-03
  • java實(shí)現(xiàn)適用于安卓的文件下載線程類

    java實(shí)現(xiàn)適用于安卓的文件下載線程類

    本文給大家分享的是java實(shí)現(xiàn)適用于安卓的文件下載線程類的代碼,有需要的小伙伴可以參考下
    2015-07-07
  • 如何發(fā)布jar包到maven中央倉庫

    如何發(fā)布jar包到maven中央倉庫

    這篇文章主要介紹了發(fā)布jar包到maven中央倉庫的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2023-12-12

最新評(píng)論

宁明县| 巧家县| 平武县| 大同县| 安义县| 比如县| 仁化县| 惠来县| 兰州市| 福泉市| 盐亭县| 肥城市| 广宗县| 鄄城县| 仙居县| 咸阳市| 揭阳市| 孙吴县| 康乐县| 肥乡县| 乌审旗| 礼泉县| 莒南县| 南和县| 噶尔县| 大新县| 浦城县| 介休市| 潼关县| 龙海市| 武汉市| 修水县| 西藏| 中西区| 介休市| 佛坪县| 山东省| 广西| 仁怀市| 阿尔山市| 黎平县|