Java 系統工程開發過程中,都會有各個層之間的對象轉換,比如 VO、DTO、PO、VO 等,而如果都是手動get、set又太浪費時間,還可能操作錯誤,是以選擇一個自動化工具會更加友善;
Spring copyProperties
org.springframework.beans.BeanUtils
這個方法是反射的屬性拷貝,Spring 提供的 copyProperties 要比 Apache 好用得多,性能和操作都比較好
BeanUtils.copyProperties(queryVo,param);
裡面已經有空值校驗:
Assert.notNull(source, "Source must not be null");
這是斷言,由于斷言固定抛出AssertionError異常,是以在公共方法中最好不要用,因為如果抛出異常很難辨識出這是什麼原因導緻的。
Cglib BeanCopier
org.springframework.cglib.beans.BeanCopier
的原理與Beanutils 原理不太一樣,其主要是使用 位元組碼技術動态生成一個代理類,代理類實作get 和 set方法。
生成代理類過程存在一定開銷,但是一旦生成,我們可以緩存起來重複使用,
是以 Cglib 性能相比Beanutils 性能比較好整體性能不錯,使用也不複雜
BeanCopier beanCopier =
BeanCopier.create(SendEnterpriseInfo.class, SalesmanEnterpriseDft.class,false);
beanCopier.copy(enterpriseDto,enterpriseDft,null);
這裡介紹一個封裝的寫法,可以參考一下:
private static final Map<BeanCopierUtil.ClassKey, BeanCopier>
BEAN_COPIER_WITH_CONVERTER_CACHE
= new ConcurrentHashMap();
public static BeanCopier genBeanCopierWithConverter(Object source, Object target) {
Assert.notNull(source, "源對象不能為空");
Assert.notNull(target, "目标對象不能為空");
BeanCopierUtil.ClassKey classKey = buildClassKey(source, target);
BeanCopier beanCopier = (BeanCopier)
BEAN_COPIER_WITH_CONVERTER_CACHE.get(classKey);
if (beanCopier == null) {
BeanCopier newBeanCopier =
BeanCopier.create(classKey.sourceClass, classKey.targetClass, true);
BeanCopier oldBeanCopier =
(BeanCopier)BEAN_COPIER_WITH_CONVERTER_CACHE.putIfAbsent(classKey, newBeanCopier);
beanCopier = oldBeanCopier != null ? oldBeanCopier : newBeanCopier;
}
return beanCopier;
}
public static BeanCopierUtil.ClassKey buildClassKey(Object source, Object target) {
if (source != null && target != null) {
Class<?> sourceClazz = source.getClass();
Class<?> targetClazz = target.getClass();
return new BeanCopierUtil.ClassKey(sourceClazz, targetClazz);
} else {
return null;
}
}
private static class ClassKey {
private Class<?> sourceClass;
private Class<?> targetClass;
public ClassKey(Class<?> sourceClass, Class<?> targetClass) {
this.sourceClass = sourceClass;
this.targetClass = targetClass;
}
public boolean equals(Object o) {
if (this == o) {
return true;
} else if (o != null && this.getClass() == o.getClass()) {
BeanCopierUtil.ClassKey classKey = (BeanCopierUtil.ClassKey)o;
return !Objects.equals(this.sourceClass, classKey.sourceClass) ? false : Objects.equals(this.targetClass, classKey.targetClass);
} else {
return false;
}
}
public int hashCode() {
int result = this.sourceClass != null ? this.sourceClass.hashCode() : 0;
result = 31 * result + (this.targetClass != null ? this.targetClass.hashCode() : 0);
return result;
}
}
總結: 優先使用 Cglib BeanCopier
如果你想真的了解一個原理,最好是可以把它用自己的話分享出來!
分享明智;程式和産品設計;一起交流進步!