声明:本文属原创文章,始发于公号:程序员自学之道,并同步发布于 https://blog.youkuaiyun.com/dadiyang 转载请注明出处!
缘起
有一次开发过程中,刚好看到一个小伙伴在调用 set 方法,将一个数据库中查询出来的 PO 对象的属性拷贝到 Vo 对象中,类似这样:
可以看出,Po 和 Vo 两个类的字段绝大部分是一样的,我们一个个地调用 set 方法只是做了一些重复的冗长的操作。这种操作非常容易出错,因为对象的属性太多,有可能会漏掉一两个,而且肉眼很难察觉。
类似这样的操作,我们可以很容易想到,可以通过反射来解决。其实,如此普遍通用的功能,一个 BeanUtils 工具类就可以搞定了。
于是我建议这位小伙伴使用了 Apache BeanUtils.copyProperties 进行属性拷贝,这为我们的程序挖了一个坑!
阿里代码规约
当我们开启阿里代码扫描插件时,如果你使用了 Apache BeanUtils.copyProperties
进行属性拷贝,它会给你一个非常严重的警告。因为,Apache BeanUtils性能较差,可以使用 Spring BeanUtils 或者 Cglib BeanCopier 来代替。
看到这样的警告,有点让人有点不爽。大名鼎鼎的 Apache 提供的包,居然会存在性能问题,以致于阿里给出了严重的警告。
那么,这个性能问题究竟是有多严重呢?毕竟,在我们的应用场景中,如果只是很微小的性能损耗,但是能带来非常大的便利性,还是可以接受的。
带着这个问题。我们来做一个实验,验证一下。
如果对具体的测试方式没有兴趣,可以跳过直接看结果哦~
测试方法接口和实现定义
首先,为了测试方便,让我们来定义一个接口,并将几种实现统一起来:
public interface PropertiesCopier {
void copyProperties(Object source, Object target) throws Exception;
}
public class CglibBeanCopierPropertiesCopier implements PropertiesCopier {
@Override
public void copyProperties(Object source, Object target) throws Exception {
BeanCopier copier = BeanCopier.create(source.getClass(), target.getClass(), false);
copier.copy(source, target, null);
}
}
// 全局静态 BeanCopier,避免每次都生成新的对象
public class StaticCglibBeanCopierPropertiesCopier implements PropertiesCopier {
private static BeanCopier copier = BeanCopier.create(Account.class, Account.class, false);
@Override
public void copyProperties(Object source, Object target) throws Exception {
copier.copy(source, target, null);
}
}
public class SpringBeanUtilsPropertiesCopier implements PropertiesCopier {
@Override
public void copyProperties(Object source, Object target) throws Exception {
org.springframework.beans.BeanUtils.copyProperties(source, target);
}
}
public class CommonsBeanUtilsPropertiesCopier implements PropertiesCopier {
@Override
public void copyProperties(Object source, Object target) throws Exception {
org.apache