BeanUtils工具类(BeanUtils使用与原理详解)

BeanUtils工具类(BeanUtils使用与原理详解)-mikechen

BeanUtils简介

BeanUtils提供对Java反射和自省API的包装,其主要目的是利用反射机制对JavaBean的属性进行处理,简化JavaBean封装数据的操作。

BeanUtils工具类的实现主要包含:Apache commons包实现的BeanUtils工具类,以及spring-beans实现的BeanUtils的工具类。

 

为什么要使用BeanUtils

在我们实际项目开发过程中,我们经常需要将不同的两个对象实例进行属性复制,从而基于源对象的属性信息进行后续操作,而不改变源对象的属性信息。

比如DTO数据传输对象和数据对象DO,我们需要将DO对象进行属性复制到DTO,但是对象格式又不一样,所以我们需要编写映射代码将对象中的属性值从一种类型转换成另一种类型。

通常会调用其set/get方法,有些时候,但是我们很不喜欢写很多冗长的b.setF1(a.getF1())这样的代码,于是我们需要简化对象拷贝方式。

为了解决这一痛点,就诞生了一些方便的BeanUtils类库,比如:常用的有 apache的 BeanUtils,spring的 BeanUtils等拷贝工具类。

 

Apache 的 BeanUtils

首先来看一个非常简单的BeanUtils的例子,代码如下:

public class PersonSource  {
    private Integer id;
    private String username;
    private String password;
    private Integer age;
    // getters/setters omiited
}

public class PersonDest {
    private Integer id;
    private String username;
    private Integer age;
    // getters/setters omiited
}

public class TestApacheBeanUtils {
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
       //下面只是用于单独测试
        PersonSource personSource = new PersonSource(1, "mikechen", "12345", 35);
        PersonDest personDest = new PersonDest();
        BeanUtils.copyProperties(personDest,personSource);
        System.out.println("persondest: "+personDest);
    }
}
persondest: PersonDest{id=1, username='mikechen', age=35}

从上面的例子可以看出,对象拷贝非常简单,BeanUtils最常用的方法就是:

//将源对象中的值拷贝到目标对象
public static void copyProperties(Object dest, Object orig) throws IllegalAccessException, InvocationTargetException {
    BeanUtilsBean.getInstance().copyProperties(dest, orig);
}

默认情况下,使用org.apache.commons.beanutils.BeanUtils对复杂对象的复制是引用,这是一种浅拷贝。

浅拷贝:对基本数据类型进行值传递,对引用数据类型,使用其引用地址,不拷贝其内容,此为浅拷贝

深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝。

但是由于 Apache下的BeanUtils对象拷贝性能太差,不建议使用,而且在阿里巴巴Java开发规约插件上也明确指出,避免用Apache Beanutils进行属性的copy。

为什么《阿里巴巴Java开发手册》中提到禁止使用Apache BeanUtils呢?

深复制(深克隆)被复制对象的所有变量都含有与原来的对象相同的值,除去那些引用其他对象的变量,那些引用其他对象的变量将指向被复制过的新对象,而不再试原有的那些被引用的对象,换言之,深复制把要复制的对象所引用的对象都复制了一遍。

 

Spring的 BeanUtils

如果想用BeanUtils工具,一般会建议使用Spring BeanUtils的实现。

看一个简单的例子,使用spring的BeanUtils进行对象拷贝,代码如下:

class A{
    string id;
    string name;
    string age;
    string sex;
}
 
class B{
    string id;
    string name;
}

假如:想把一个类A中的一些属性的值,设置到另一个类B的属性中。

方法1:new 对象,然后把值一个一个的set。

B b=new B();
A a=new A();
b.setId(a.getId());
b.setName(a.getName());

方式2:BeanUtils.copyProperties(import org.springframework.beans.BeanUtils;)

BeanUtils.copyProperties(A,B);

Spring下的BeanUtils也是使用 copyProperties方法进行拷贝,只不过它的实现方式非常简单,就是对两个对象中相同名字的属性进行简单的get/set,仅检查属性的可访问性。

注意点:A中要复制的属性,一定要和B中的属性 相同!

 

Spring的BeanUtils与Apache的BeanUtils区别

BeanUtils工具类(BeanUtils使用与原理详解)-mikechen

 

BeanUtils总结

以上简要的分析两种BeanUtils,因为Apache下的BeanUtils性能较差,不建议使用,可以使用 Spring的BeanUtils,或者使用其他拷贝框架,比如 cglib BeanCopier,基于javassist的Orika等,这些也是非常优秀的类库,值得去尝试。

 

 

作者简介

陈睿|mikechen,10年+大厂架构经验,BAT资深面试官,就职于阿里巴巴、淘宝、百度等一线互联网大厂。

👇阅读更多mikechen架构文章👇

阿里架构 |双11秒杀 |分布式架构 |负载均衡 |单点登录 |微服务 |云原生 |高并发 |架构师

以上

关注作者「mikechen」公众号,获取更多技术干货!

后台回复架构,即可获取《阿里架构师进阶专题全部合集》,后台回复面试即可获取《史上最全阿里Java面试题总结

评论交流
    说说你的看法