BeanUtils 初探

来源:互联网 发布:秩为1矩阵的几 编辑:程序博客网 时间:2024/06/16 04:10

实习的时候碰上有人用BeanUtils,感觉很方便,省了很多胶水代码的工作,但是自己当时用的时候,发现它还是有一些问题,但是没有仔细琢磨,现在有时间了,琢磨一下.

Apache common.BeanUtils 作用

BeanUtils提供了一些方法,用来从一个简单的Java对象(JavaBean)中,提出属性,或者实现给其他JavaBean拷贝属性.
这样,就可以省略此前容易出错的各种通过setter的方式DO转DTO等的工具方法.

原理

JDK提供了内省的机制,对JavaBean类型的类做了额外的工具来获取,设置,遍历属性.内省机制是通过私有属性的公开getter/setter方法来实现的,所以,BeanUtils能操作的属性,必须有公开的getter/setter方法,否则,BeanUtils默认这个JavaBean没有对应属性.
内省机制的基础,自然是Java的反射机制.

参考

深入理解JavaBean(1):JavaBean的内省与BeanUtils库

方法介绍

copyProperties(Object dest,Object orig)

这个方法是用的最多的了吧,功能就是把源(orig)JavaBean的各种属性,拷贝给目标(dest)JavaBean.

需要注意的是:

  1. 源和目标的属性名应当完全一样
  2. 这个方法可以一定限度内将相同属性名,但是类型不同的属性做一个转化,如果确定没有这种需求的话,可以使用PropertyUtilscopyProperties方法,PropertyUtils更快一点.
  3. 属性不是数组或者Mapl类型,并且没有getter,setter方法的,这个方法不能拷贝
  4. 这个方法和另一个方法populate(Object dest,Map properties)类似,不同点是populate专用来处理需要被拷贝的属性存放在map中的情况,而copyProperties无此限制.
  5. 对于java.util.Date类型的属性,如果源JavaBean为null,那么使用该方法会抛异常,可以通过自定义类继承BeanUtils,内容如下,来避免这个问题
import org.apache.commons.beanutils.BeanUtils;import org.apache.commons.beanutils.ConvertUtils;import org.apache.commons.beanutils.converters.DateConverter;import java.lang.reflect.InvocationTargetException;import java.util.Date;public class BeanUtilsEx extends BeanUtils {    static{        //这里,如果源为null,这里的设置目标的默认值为null,自然,也可以设置为其他        ConvertUtils.register(new DateConverter(null),Date.class);    }    //覆盖父类方法    public static void copyProperties(Object dest,Object orig){        try {            BeanUtils.copyProperties(dest,orig);        } catch (IllegalAccessException e) {            e.printStackTrace();        } catch (InvocationTargetException e) {            e.printStackTrace();        }    }}

参考

  1. BeanUtils.copyProperties属性拷贝日期为空异常
  2. copyProperties文档

populate方法

功能与上面提到的copyProperties类似,只是入参的源是Map

cloneBean(Object bean)

用于利用入参的JavaBean,生成一个一样的JavaBean,返回值是Object,需要显式转换

需要注意的是:

  1. 不需要源Bean实现Clonable
  2. 拷贝是浅拷贝,属性共用同一个对象

describe(Object bean)

从源Bean中,用属性名和属性的值,填充一个Map,返回

需要注意的是:

  1. 返回的Map不是泛型的,但是key和value都是String类型,value不是String 类型的会被BeanUtils内的Convert转换成String

参考

  1. BeanUtils.describe与PropertyUtils.describe区别

getMappedProperty(Object bean,String name,String key) 与 getMappedProperty(Object bean,String name)

从源Java中提取指定Map类型,属性名为入参name的属性,返回值转换成String.
由于是Map类型,所以进一步的属性值,需要通过Map的key来指定,所以有了第三个参数String key,对于使用getMappedProperty(Object bean,String name)的形式,key需要拼接到参数name中,类似与"mapParam(key)"

使用示例

public class Pojo{    private Map<String,String> param;    public Map<String,String> getParam(){return param;}    public void setParam(Map<String,String> param){this.param=param;}}public class BeanUtilsTest{    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException{        Map<String String> map=new HashMap<>();        map.put("test1","1");        map.put("test2","2");        Pojo pojo=new Pojo();        BeanUtils.copyProperty(pojo,"param",map);        System.out.println(BeanUtils.getMappedProperty(pojo,"param(test1)"));        System.out.println(BeanUtils.getMappedProperty(pojo,"param","test2"));    }}

getIndexedProperty(Object bean,String name,int index) 与 getIndexedProperty(Object bean,String name)

getMappedProperty(Object bean,String name,String key)getMappedProperty(Object bean,String name)类似,不过这次源Bean内的属性是数组,此外,name的形式也有不同,从Mapped的那种map(key),要改成array[index]的形式.