对象拷贝工具类抽取-2022新项目
一、业务场景
项目开发中,经常需要进行类与类之间的拷贝,比如请求时,InVO需要转换为DTO,业务层处理时,需要将DTO转换成
Aggregate对象;在进行数据库操作时,需要将Aggregate对象转换为queryDTO对象;数据返回时,需要将PO对象转换为Aggregate
对象进行返回,最后将Aggregate对象转换为outVO对象返回到页面中。这种操作即使是写一个简单的接口,也会非常地麻烦,需要将
对象进行不断地转换。一个简单的接口请求过程为: InVO--->DTO--->Aggregate--->queryDTO--->PO--->Aggregate--->OutVO。这还只
是简单的操作,如果分页操作会更加的麻烦,因为从数据库取到的数据不能直接返回,需要逐层返回,还需要携带分页信息处理起来
会更加麻烦。
注释: Aggregate 是DDD中的术语,表示聚合根。
二、需求分析
面对繁多的对象转换,自己在考虑一个问题,能否将这些重复地操作抽取为公共的工具类呢,每次需要转换的时候直接调
用公共的服务类即可,这样可以大大滴减少代码量。粗略估计一下,少说能够省下三分之一到四分之一的代码量,以写一个接口
为例,光是转换就花了不少时间。并且还是一些重复地没什么技术含量的代码。如果能把这些时间省下来,可以用于开发更加有
意义的业务代码,而不是写一些低级的对象拷贝代码。
三、解决方案
决定写这个工具类后,自己就开始来构思这个工具类应该怎么来写,总体来说这个工具类中只需要两个方法即可,一个是将
单个对象转换为另外一个对象,一个是将一个集合转换为另外一个集合,有时候可能有列表查询。从第一个方法开始,自己设想这
个方法应该只有两个参数,一个是原对象,一个待转换后的对象。可是待换后的对象用什么来表示呢?很快找到一个答案使用class
来当做参数,处理的时候先通过反射获取class的实例,然后在使用spring中提供的工具类进行数据的拷贝。经过反反复复地调试,
改进最终写好的工具类如下:
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @Author 一只爱阅读的程序员
* @Description bean转换工具类
* @Date 2022/7/15 21:50
* @Version 1.0
*/
@Slf4j
public class BeanTransforUtils {
/* @Description: 根据class文件获取对象实例
* @author: 一只爱阅读的程序员
* @date: 2022/7/15 21:56
* @param: clazz
* @return: E
*/
private static final<E> E getInstance(final Class<E> clazz) {
if (clazz == null) {
return null;
}
try {
return clazz.newInstance();
} catch (InstantiationException | IllegalAccessException error) {
BeanTransforUtils.log.error(clazz.toString() + "-方法-getInstance-获取实例错误: " + error.getMessage(), error);
throw new RuntimeException(clazz.toString() + "-方法-getInstance-获取实例错误");
}
}
/* @Description: 将一个对象转换为一个新对象
* @author: 一只爱阅读的程序员
* @date: 2022/7/15 22:01
* @param: source
* @param: clazz
* @return: E
*/
public static final<E> E transforNewObject(Object source, final Class<E> clazz) {
if (source == null || clazz == null) {
return null;
}
E instance = BeanTransforUtils.getInstance(clazz);
if (instance == null) {
return null;
}
BeanUtils.copyProperties(source, instance);
return instance;
}
/* @Description: 把一个集合转换为一个新的集合
* @author: 一只爱阅读的程序员
* @date: 2022/7/15 22:10
* @param: sourceList
* @param: clazz
* @return: List<E>
*/
public static final <E> List<E> transforNewObjectList(List<?> sourceList, final Class<E> clazz) {
if (clazz == null || sourceList == null || sourceList.size() < 1){
return Collections.emptyList();
}
List<E> targetList = new ArrayList<>(sourceList.size());
sourceList.forEach(item->{
E e = BeanTransforUtils.transforNewObject(item, clazz);
targetList.add(e);
});
return targetList;
}
}
源代码是写在公司的内网中的,不能直接拿到,反正是自己写的,就在自己电脑上面在写一次。
工具类中主要有三个方法,第一个方法是私有的,根据传入的class对象获取一个实例对象;
第二个方法是通过传入的对象实例和一个class对象,将一个对象中的数据复制到另外一个对象中;
第三个方法是通过传入的集合对象和一个class对象,将一个集合转换为一个新的集合,有时候是列表查询。
参考文章如下:
https://www.cnblogs.com/xwb583312435/p/8672622.htm
https://blog.csdn.net/weixin_45774350/article/details/114981074
经过测试,发现这种方式完全可行。最后去询问负责人能否使用这个工具类进行对象的拷贝,得到的答案是暂时
不允许使用。心都拔凉拔凉的,只能听大佬的,以此分享出来,希望其他小伙伴能够用得上。如果有可以改进的
地方,欢迎各位留言。
好消息是负责人已经同意使用,现在已经在项目中真正用起来,大大地简化了Bean转化的代码,提升了开发效率!
项目的新版本已经正式上线,目前未发现异常,一切都很顺利!这个工具类也发挥了它极大的作用。在这个转换类
的基础之上,还可以对分页对象做进一步的封装处理,在调用的时候,直接调用封装的方法。这样处理起来会更加
的方便。这个工具类可以好不夸张的说,起到的作用是事半功倍的,这是经验的总结,如果以后项目中允许使用的话,
自己也会毫不犹豫的继续使用,提升自己的开发效率,其中之一的一个方法就是抽取公共的代码。