一、简介:
BeanUtils提供对Java反射和自省API的包装。其主要目的是利用反射机制对JavaBean的属性进行处理。我们知道,一个JavaBean通常包含了大量的属性,很多情况下,对JavaBean的处理导致大量get/set代码堆积,增加了代码长度和阅读代码的难度。
二、用法:
如果你有两个具有很多相同属性的JavaBean,一个很常见的情况就是Struts里的PO对象(持久对象)和对应的ActionForm。例如:一个用户注册页面,有一个User实体类和一个UserActionForm,我们一般会在Action里从ActionForm构造一个PO对象,传统的方式是使用类似下面的语句对属性逐个赋值:
Java代码
- // 获取 ActionForm 表单数据
- UserActionForm uForm = (UserActionForm) form;
- // 构造一个User对象
- User user = new User();
- // 逐一赋值
- user.setUsername(uForm.getUsername);
- user.setPassword(uForm.getPassword);
- user.setAge(uForm.getAge);
- ...........
- ...........
- // 然后调用JDBC、或操作Hibernate 持久化对象User到数据库
- ...
通过这样的方法如果表单数据N多、100、1000(夸张点。哈哈)、、、、那我们不是要写100、、、1000行set、get了。谁都不愿意这样做。
而我们使用 BeanUtils.copyProperties() 方法以后,代码量大大的减少,而且整体程序看着也简洁明朗,代码如下:
Java代码
- // 获取 ActionForm 表单数据
- UserActionForm uForm = (UserActionForm) form;
- // 构造一个User对象
- User user = new User();
- // 赋值
- BeanUtils.copyProperties(user, uForm);
- // 然后调用JDBC、或操作Hibernate 持久化对象User到数据库
- .......
注:如果User和UserActionForm 间存在名称不相同的属性,则BeanUtils不对这些属性进行处理,需要手动处理。例如:
User类里面有个createDate 创建时间字段,而UserActionForm里面无此字段。BeanUtils.copyProperties()不会对此字段做任何处理。必须要自己手动处理。
用法总结如下:
[java] view plain copy print?
- BeanUtils.copyProperties("转换后的类", "要转换的类");
[java] view plain copy print?
- 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 +
'}';
}
}