您的位置:首页 > 运维架构

关于BeanUtils中copyProperties方法的研究体会

2012-07-23 10:01 351 查看
下面的都是我转来的-------------------------------------------------------------------------

在Struts中经常看到BeanUtils.copyProperties这个方法满天飞,特别是在提取表单中的值的时候,但是这个方法具体怎么实现属性的复制却一直不是很明白,特别是在复制属性的时候,比方说把b复制到a,BeanUtils.copyProperties(a,b),是不是把b的所有属性都复制过去了呢?如果是同一个属性,b中的值是不是会覆盖掉a中的值?这些应该都可以从BeanUtils的源码中得到答案,奈何找了半天没找到源码,在网上也没有找到别人的答复,于是本着实践是检验真理的唯一标准,决定亲自测试一把,^_^。

首先我们构建两个类People和Person,它们的实例呆会会用来相互复制。

People.java:

package com.mangocity.test;
 
/**
 *@authorCMTobby
 */
publicclass People {
 
    public People() {
       //
TODO Auto-generated constructor stub
    }
   
    private String
name;//姓名
    privateintage;//年龄
    private String
email;
   
    public String getEmail() {
       returnemail;
    }
    publicvoid setEmail(String email) {
       this.email = email;
    }
    publicint getAge() {
       returnage;
    }
    publicvoid setAge(int
age) {
       this.age = age;
    }
    public String
getName() {
       returnname;
    }
    publicvoid setName(String name) {
       this.name = name;
    }
}
 
 
Person.java:

package com.mangocity.test;
 
/**
 *@authorCMTobby
 */
publicclass Person {
    private String
name;
    privateintage;
    private String
address;
   
    public String getAddress() {
       returnaddress;
    }
    publicvoid setAddress(String address) {
       this.address = address;
    }
    publicint getAge() {
       returnage;
    }
    publicvoid setAge(int
age) {
       this.age = age;
    }
    public String getName() {
       returnname;
    }
    publicvoid setName(String name) {
       this.name = name;
    }
}

 

接着构建我们的测试类

import org.apache.commons.beanutils.*;
publicclass TestBeanUtils {
 
    /**
     *@paramargs
     */
    publicstaticvoid main(String[] args) {
       //
TODO Auto-generated method stub
       People tobby=new People();
       Person cindy=new Person();
       tobby.setAge(23);
       tobby.setName("CMTobby");
       tobby.setEmail("xiaozhu87487705@163.com");
 
       cindy.setName("Cindyelf");
       cindy.setAge(24);
        try {
             BeanUtils.copyProperties(cindy, tobby);
           System.out.println(cindy.getName()+":"+cindy.getAge());
       } catch (IllegalAccessException e) {
           //
TODO Auto-generated catch block
           e.printStackTrace();
       } catch (InvocationTargetException e) {
           //
TODO Auto-generated catch block
           e.printStackTrace();
       }
    }
}

 

运行该程序输出是:CMTobby:23。这说明经过BeanUtils.copyProperties之后cindy中name和age属性的值已经被tobby中的同名属性给“覆盖”了,至于tobby中有而cindy中没有的email属性有没有复制到cindy中就不得而知了,据我的猜测应该是没有的,因为在cindy中没有地方放这个属性啊,而且就算复制过去了,我们如何得到这个值呢?难道用cindy.getEmail()吗,可是cindy根本没有这个方法啊?当然这只是我的猜测,不知哪位达人有准确的答案,欢迎指正,^_^。

那么这个复制过程是如何的呢?是直接属性对属性的值拷贝吗,例如cindy.name=tobby.name?还是老办法,将测试进行到底。

1.我将Person中的name属性改名为name11,age属性改为age11,get和set方法都做相应的修改,此时运行程序,输出结果为:CMTobby:23,和前面的一样,由此可以排除值拷贝这个假设了,因为此时cindy中没有了name属性而是name11属性。

2.我将Person中的setName和setAge方法分别改为setName11和setAge11.OK,再次运行我们的程序,这时的输出是:Cindyelf:24,我们发现cindy的name属性和age属性的值都没有被覆盖掉,也就是说tobby中的值都没有拷贝过来,为什么呢?

3.将我们程序恢复到刚开始的样子,即上面所贴的代码那样,然后将Person中的setAge方法注释掉,并注释掉TestBeanUtils中的cindy.setAge(24)这行代码。运行程序,输出结果是:CMTobby:0。tobby中age属性的值没有拷贝过来,为什么呢?

基于上述两个测试,我猜测BeanUtils.copyProperties的行为过程是这样的:首先通过java的反射得到tobby中的所有域,然后根据域的名字调用cindy中相应的set方法。举个例子,BeanUtils发现tobby中有个name属性,那么它会尝试执行cindy.setName()这个方法。这就很容易解释测试2和测试3的结果了:因为cindy中没有了setName或者setAge(被改成了setName11和setAge11或者被注释掉了),所有cindy的name属性不会变,仍然是以前的值。而在测试1中,因为cindy对象有setName方法,所以name11属性的值会被覆盖掉。

做完上述测试之后,我闲着无聊又做了如下两个测试:

4.将Person中的setName和setAge改为setname和setage,程序输出结果是:CMTobby:23,cindy中的name属性和age属性的值都发生了变化;

5.将Person中的setName和setAge改为setNAme和setAGe,程序输出结果是:Cindyelf:24,tobby中的属性的值都没有拷贝过来。
基于这两个测试,我想过程会不会是这样的:如果BeanUtils发现tobby中有个name属性,那么它就会尝试执行cindy.setName()或者cindy.setname()。当然这些都只是我的推论,仅供参考,所有的答案都会在BeanUtils的源码中找到,^_^,还望哪位达人不吝告知。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息