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

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

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

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之后cindynameage属性的值已经被tobby中的同名属性给“覆盖”了,至于tobby中有而cindy中没有的email属性有没有复制到cindy中就不得而知了,据我的猜测应该是没有的,因为在cindy中没有地方放这个属性啊,而且就算复制过去了,我们如何得到这个值呢?难道用cindy.getEmail()吗,可是cindy根本没有这个方法啊?当然这只是我的猜测,不知哪位达人有准确的答案,欢迎指正,^_^

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

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

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

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

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

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

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

5.Person中的setNamesetAge改为setNAmesetAGe,程序输出结果是:Cindyelf:24tobby中的属性的值都没有拷贝过来。

基于这两个测试,我想过程会不会是这样的:如果BeanUtils发现tobby中有个name属性,那么它就会尝试执行cindy.setName()或者cindy.setname()。当然这些都只是我的推论,仅供参考,所有的答案都会在BeanUtils的源码中找到,^_^,还望哪位达人不吝告知。

posted on 2010-12-31 17:51  草原和大树  阅读(4155)  评论(2编辑  收藏  举报