Beanutils.copyProperties( )用法及重写提高效率

一、简介:

        BeanUtils提供对Java反射和自省API的包装。其主要目的是利用反射机制对JavaBean的属性进行处理。我们知道,一个JavaBean通常包含了大量的属性,很多情况下,对JavaBean的处理导致大量get/set代码堆积,增加了代码长度和阅读代码的难度。

 

 

二、用法:

        

        如果你有两个具有很多相同属性的JavaBean,一个很常见的情况就是Struts里的PO对象(持久对象)和对应的ActionForm。例如:一个用户注册页面,有一个User实体类和一个UserActionForm,我们一般会在Action里从ActionForm构造一个PO对象,传统的方式是使用类似下面的语句对属性逐个赋值:

 

Java代码 

  1. // 获取 ActionForm 表单数据  
  2.   
  3. UserActionForm uForm = (UserActionForm) form;  
  4.   
  5.   
  6.   
  7. // 构造一个User对象  
  8.   
  9. User user = new User();  
  10.   
  11.   
  12.   
  13. // 逐一赋值  
  14. user.setUsername(uForm.getUsername);  
  15.   
  16. user.setPassword(uForm.getPassword);  
  17.   
  18. user.setAge(uForm.getAge);  
  19.   
  20. ...........  
  21.   
  22.   
  23.   
  24. ...........  
  25.   
  26.   
  27.   
  28. // 然后调用JDBC、或操作Hibernate 持久化对象User到数据库  
  29.   
  30. ...  

 

通过这样的方法如果表单数据N多、100、1000(夸张点。哈哈)、、、、那我们不是要写100、、、1000行set、get了。谁都不愿意这样做。

 而我们使用 BeanUtils.copyProperties() 方法以后,代码量大大的减少,而且整体程序看着也简洁明朗,代码如下:

 

Java代码  

  1. // 获取 ActionForm 表单数据  
  2.   
  3. UserActionForm uForm = (UserActionForm) form;  
  4.   
  5.    
  6.   
  7. // 构造一个User对象  
  8.   
  9. User user = new User();  
  10.   
  11.   
  12. // 赋值  
  13.   
  14.    
  15.   
  16. BeanUtils.copyProperties(user, uForm);  
  17.   
  18.   
  19.   
  20.   
  21.   
  22. // 然后调用JDBC、或操作Hibernate 持久化对象User到数据库  
  23.   
  24. .......  

 

注:如果User和UserActionForm 间存在名称不相同的属性,则BeanUtils不对这些属性进行处理,需要手动处理。例如:

User类里面有个createDate 创建时间字段,而UserActionForm里面无此字段。BeanUtils.copyProperties()不会对此字段做任何处理。必须要自己手动处理。

 

用法总结如下:

 

[java] view plain copy  print?

  1. BeanUtils.copyProperties("转换后的类", "要转换的类");  

[java] view plain copy  print?

  1. PropertyUtils.copyProperties("转换后的类", "要转换的类");  

用法其实很简单,第一个参数是转换后的类,第二个参数是待转换的类

 

 

 

实例:

BeanUtils提供对Java反射和自省API的包装。其主要目的是利用反射机制对JavaBean的属性进行处理。我们知道,一个JavaBean通常包含了大量的属性,很多情况下,对JavaBean的处理导致大量get/set代码堆积,增加了代码长度和阅读代码的难度。

下面通过代码来理解BeanUtils

首先创建两个类

Person.java

package com.org;
 
import java.util.Date;
 
public class Person {
    private String name;
    private String sex;
    private int age;
    private Date birthday;
 
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getSex() {
        return sex;
    }
 
    public void setSex(String sex) {
        this.sex = sex;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
 
    public Date getBirthday() {
        return birthday;
    }
 
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    
 
}

Student.java
package com.org;
 
import java.util.Date;
 
public class Student {
    private String name;
    private int age;
    private String address;
    private Date birthday;
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    public Date getBirthday() {
        return birthday;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    
    
}

测试类  BeanUtilTest.java
package com.org;
 
import java.lang.reflect.InvocationTargetException;
import java.util.Date;
 
//import com.sun.org.apache.commons.beanutils.BeanUtils;注意着两个import的区别
 
import org.apache.commons.beanutils.BeanUtils;
 
public class BeanUtilTest {
    public static void main(String[] args) {
        Person per = new Person();
        Student stu = new Student();
        
        per.setName("zhangsan");
        per.setSex("男");
        per.setAge(20);
        per.setBirthday(new Date());
        
        stu.setName("wuangwu");
        stu.setAddress("北京市");
        try {
            BeanUtils.copyProperties(stu, per);
            
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println(stu.getName());
        System.out.println(stu.getAge());
        System.out.println(stu.getAddress());
        System.out.println(stu.getBirthday());
        
    }
}

程序输出结果为:
zhangsan
20
北京市
Fri Nov 25 13:03:29 CST 2011

可见Student自己设置的值都被Person给覆盖了 
再做下面两个测试

把Person中的setName和setAge 改为setname  setage程序输出结果为

zhangsan
20
北京市
Fri Nov 25 13:08:34 CST 2011

结果没有改变
而如果改为setNAme, setAGe结果为:

wuangwu
0
北京市
Fri Nov 25 13:10:25 CST 2011

我们发现结果改变了  内容没有被覆盖
注: 当我们加载BeanUtils类时 可能会报如下错误

Exception in thread "main" java.lang.ExceptionInInitializerError
    at com.org.BeanUtilTest.main(BeanUtilTest.java:101)
Caused by: com.sun.org.apache.commons.logging.LogConfigurationException: com.sun.org.apache.commons.logging.LogConfigurationException: java.lang.NullPointerException (Caused by java.lang.NullPointerException) (Caused by com.sun.org.apache.commons.logging.LogConfigurationException: java.lang.NullPointerException (Caused by java.lang.NullPointerException))
    at com.sun.org.apache.commons.logging.impl.LogFactoryImpl.newInstance(LogFactoryImpl.java:543)
    at com.sun.org.apache.commons.logging.impl.LogFactoryImpl.getInstance(LogFactoryImpl.java:235)
    at com.sun.org.apache.commons.logging.impl.LogFactoryImpl.getInstance(LogFactoryImpl.java:209)
    at com.sun.org.apache.commons.logging.LogFactory.getLog(LogFactory.java:351)
    at com.sun.org.apache.commons.beanutils.BeanUtils.<clinit>(BeanUtils.java:111)
    ... 1 more
Caused by: com.sun.org.apache.commons.logging.LogConfigurationException: java.lang.NullPointerException (Caused by java.lang.NullPointerException)
    at com.sun.org.apache.commons.logging.impl.LogFactoryImpl.getLogConstructor(LogFactoryImpl.java:397)
    at com.sun.org.apache.commons.logging.impl.LogFactoryImpl.newInstance(LogFactoryImpl.java:529)
    ... 5 more
Caused by: java.lang.NullPointerException
    at com.sun.org.apache.commons.logging.impl.LogFactoryImpl.getLogConstructor(LogFactoryImpl.java:374)
    ... 6 more

三、接下来下讲一下org.springframework.beans.Beanutils copyProperties 原理

BeanUtils. copyProperties(source,targe)原理:
根据source的属性来向target同名属性设值。 
若target无该属性,则不设
名字相同,基本类型和封装类型可以完成映射
若target有source无,则target属性值为null(基本类型则为初始值,如int 为 0)
调用原理 target.set + source的属性名(source.get + source的属性名):所有source必须有get方法,target必须有set方法
下面是例子

import org.springframework.beans.BeanUtils;

public class BeanUtilsTest {
    public static void main(String[] args) {
        Source source = new Source() {{
            setId(1111111);
        }};

        Target target = new Target();
        BeanUtils.copyProperties(source,target);
        System.out.println(source);
        System.out.println(target);

    }
}


class Source {
    int id;

    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    @Override
    public String toString() {
        return "Cat{" +
                "id=" + id +
                '}';
    }
}

class Target {
    // id换名 则无法赋值
    Integer id;
    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "id=" + id +
                '}';
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值