分享

关于BeanUtils中copyProperties方法

 WindySky 2011-06-18
关于BeanUtils中copyProperties方法的研究体会(引用)

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

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

People.java:

package com.mangocity.test;

 

/**

* @author CMTobby

*/

public class People {

 

        public People() {

           // TODO Auto-generated constructor stub

        }

    

        private String name;//姓名

        private int age;//年龄

        private String email;

    

        public String getEmail() {

           return email;

        }

        public void setEmail(String email) {

           this.email = email;

        }

        public int getAge() {

           return age;

        }

        public void setAge(int age) {

           this.age = age;

        }

        public String getName() {

           return name;

        }

        public void setName(String name) {

           this.name = name;

        }

}

 

 

Person.java:

package com.mangocity.test;

 

/**

* @author CMTobby

*/

public class Person {

        private String name;

        private int age;

        private String address;

    

        public String getAddress() {

           return address;

        }

        public void setAddress(String address) {

           this.address = address;

        }

        public int getAge() {

           return age;

        }

        public void setAge(int age) {

           this.age = age;

        }

        public String getName() {

           return name;

        }

        public void setName(String name) {

           this.name = name;

        }

}

 

接着构建我们的测试类

import org.apache.commons.beanutils.*;

public class TestBeanUtils {

 

        /**

         * @param args

         */

        public static void 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的源码中找到,^_^,还望哪位达人不吝告知。

后继:

如果BeanUtils发现cindy中有个name属性与tobby对应,那么它会调用些name的setter改变name的值;如果BeanUtils发现cindy中有setter与tobby中相应的setter方法对应,那么它会直接调用setter方法.
                                                                                                                                

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多