Java开发手册中为什么禁止使用ApacheBeanutils进行属性的复制copy以及使用SpringBeanUtils、CglibBeanCopier、AapchePropertyUtils进行属

场景

在日常开发中,我们经常需要给对象进行赋值,通常会调用其 set/get 方法,

有些时候,如果我们要转换的两个对象之间属性大致相同,会考虑使用属性拷贝工具进行。

如我们经常在代码中会对一个数据结构封装成 DO、SDO、DTO、VO 等,而这些 Bean 中的大部分属性都是一样的,

所以使用属性拷贝类工具可以帮助我们节省大量的 set 和 get 操作

为什么java开发手册中提到禁止使用Apache BeanUtils 进行属性的copy

说明:Apache BeanUtils 性能较差,可以使用其他方案比如Spring BeanUtils,Cglib BeanCopier,注意均是浅拷贝。

注:

博客:
https://blog.csdn.net/badao_liumang_qizhi

为了验证以上原因,变写测试代码进行验证。

1、首先项目中引入Apache Beanutils 依赖

​
       <!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils -->
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.9.4</version>
        </dependency>

​

2、新建PersonDO与PersonDTO以便进行属性复制

PersonDO:

import lombok.Data;

import java.util.Date;

@Data
public class PersonDO {
    private Integer id;
    private String name;
    private Integer age;
    private Date birthday;
}

PersonDTO:

import lombok.Data;

import java.util.Date;

@Data
public class PersonDTO {
    private String name;
    private Integer age;
    private Date birthday;
}

3、构建PersonDo对象并赋值属性,并将同类别的属性复制的工具类进行一百万次测试方法的封装。

        PersonDO personDO = new PersonDO();
        personDO.setName("霸道的程序猿");
        personDO.setAge(30);
        personDO.setBirthday(new Date());
        personDO.setId(1);

4、Java中封装使用ApacheBeanUtils进行指定次数属性复制的方法

    public static void mappingByApacheBeanUtils(PersonDO personDO,int times) throws InvocationTargetException, IllegalAccessException {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        for (int i = 0; i < times; i++) {
            PersonDTO personDTO = new PersonDTO();
            org.apache.commons.beanutils.BeanUtils.copyProperties(personDTO,personDO);
        }
        stopWatch.stop();
        System.out.println("mappingByApacheBeanUtils cost:"+stopWatch.getTotalTimeMillis());
    }

5、Java中封装使用SpringBeanUtils进行指定次数属性复制的方法

    public static void mappingBySpringBeanUtils(PersonDO personDO,int times){
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        for (int i = 0; i < times; i++) {
            PersonDTO personDTO = new PersonDTO();
            org.springframework.beans.BeanUtils.copyProperties(personDO,personDTO);
        }
        stopWatch.stop();
        System.out.println("mappingBySpringBeanUtils cost:"+stopWatch.getTotalTimeMillis());
    }

6、Java中封装使用CglibBeanCopier进行指定次数属性复制的方法

    public static void mappingByCglibBeanCopier(PersonDO personDO,int times){
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        for (int i = 0; i < times; i++) {
            PersonDTO personDTO = new PersonDTO();
            BeanCopier copier = BeanCopier.create(PersonDO.class,PersonDTO.class,false);
            copier.copy(personDO,personDTO,null);
        }
        stopWatch.stop();
        System.out.println("mappingByCglibBeanCopier cost:"+stopWatch.getTotalTimeMillis());
    }

7、Java中封装使用ApachePropertyUtils进行指定次数属性复制的方法

    public static void mappingByApachePropertyUtils(PersonDO personDO,int times) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        for (int i = 0; i < times; i++) {
            PersonDTO personDTO = new PersonDTO();
            org.apache.commons.beanutils.PropertyUtils.copyProperties(personDTO,personDO);
        }
        stopWatch.stop();
        System.out.println("mappingByApachePropertyUtils cost:"+stopWatch.getTotalTimeMillis());
    }

8、以上工具类执行属性复制的次数均设置为一百万次,然后执行对比效果

总结:如果考虑性能情况的话,建议大家不要选择 Apache PropertyUtils、BeanUtils,

是因为 Apache BeanUtils 力求做得完美 , 在代码中增加了非常多的校验、兼容、日志打印等代码,

过度的包装导致性能下降严重。

猜你喜欢

转载自blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/131051166