使用 BeanUtils 降低 java 内省的使用成本

上一篇文章最后提到,java 内省的原生 api 操作依旧不方便,比如参数类型的判断。用脚趾头都想得到,一定有人写了轮子。

可以使用 BeanUtils 来简化操作。spring 有一个 BeanUtils, apache-common 也有,这里使用 apache-common 的 BeanUtils 来测试。

存在如下 javaBean:

public class User {

    private String name;

    private int age;

    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;
    }
}

1. 自动类型判断。

public void test() throws Exception {
    // init
    Class clazz = Class.forName(User.class.getName());
    Object user = clazz.newInstance();

    // set
    for (Field field : clazz.getDeclaredFields()) {
        if (field.getName().equalsIgnoreCase("name")) {
            BeanUtils.setProperty(user, field.getName(), "chengfan");
        } else {
            BeanUtils.setProperty(user, field.getName(), 22);
        }
    }

    // show
    for (Field field : clazz.getDeclaredFields()) {
        String property = BeanUtils.getProperty(user, field.getName());
        System.out.println(property);
    }
}

/*
chengfan
22
*/

可以看到,使用 BeanUtils.setProperty 方法,我们不需要关心是什么参数。

当然,该方法只能处理基本数据类型和 String, 自定义的类型依旧无法处理。当然,可以通过编写 convert 来解决这个问题。这个最后演示

2. map 转 java bean。

上面的代码还是很复杂,因为需要判断字段的名字,然后设定值,BeanUtils 可以直接将一个 map 转为 bean,当然 map 的 key 要和 bean 的字段名一样。

public void test2() throws Exception {
    // init
    Class clazz = Class.forName(User.class.getName());
    Object user = clazz.newInstance();

    Map beanMap = new HashMap();
    beanMap.put("name", "chengfan");
    beanMap.put("age", 22);

    // set
    BeanUtils.populate(user, beanMap);

    // show
    for (Field field : clazz.getDeclaredFields()) {
        String property = BeanUtils.getProperty(user, field.getName());
        System.out.println(property);
    }
}
/*
chengfan
22
*/

3. bean 转 map

2 的逆过程,不解释。

@Test
public void test3() throws Exception {
    // init
    Class clazz = Class.forName(User.class.getName());
    Object user = clazz.newInstance();

    Map beanMap = new HashMap();
    beanMap.put("name", "chengfan");
    beanMap.put("age", 22);

    // set
    BeanUtils.populate(user, beanMap);

    // trans
    Map describe = BeanUtils.describe(user);

    for (Entry entry : describe.entrySet()) {
        System.out.println(String.format("%s -- %s", entry.getKey(), entry.getValue()));
    }
}
/*
name -- chengfan
age -- 22
class -- class cn.fanhub.jysk.utilslearn.beanutils.User // 忽略它
*/


2 和 3 在哪里有应用呢?

dubbo 泛化调用


  1. convertor 的用法

比如,我的字段是一个 Date 类型,并且按照 yyyy-MM-dd 格式化,正常情况下,BeanUtils 是解析不了的,所以需要做一些操作:

public class DateBean {

    private Date date;

    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }
}
@Test
public void  test4() throws Exception {

    DateBean bean = new DateBean();

    ConvertUtils.register(new Converter() {
        public Object convert(Class aClass, Object o) {
            String p = (String)o;
            if(p== null || p.trim().length()==0){
                return null;
            }
            try{
                SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
                return df.parse(p.trim());
            }
            catch(Exception e){
                return null;
            }
        }
    }, java.util.Date.class);

    BeanUtils.setProperty(bean, "date", "2018-04-18");

    System.out.println(BeanUtils.getProperty(bean, "date"));
}

// Wed Apr 18 00:00:00 CST 2018

如果注释掉 ConvertUtils.register 会报错。

你可能感兴趣的:(使用 BeanUtils 降低 java 内省的使用成本)