编写代码时,因为分层,所以经常需要VO,DO甚至DTO等层对象进行拷贝,DO是数据库对象,VO是要展示到前端的对象,其实Spring提供的BeanUtils拷贝一般对象够了,但是对于List支持还没有,所以自己稍微对于BeanUtils扩展一下,并且对于拷贝对象添加回调方法,便于不同层转换时及时修改一些有差异的字段。
使用方法
public class TestCopyProperty {
public static void main(String[] args) {
UserDO userDO = new UserDO();
userDO.setUsername("username1");
userDO.setEmail("asd@asd.com");
UserVO userVO = BeanCopyUtil.copyProperties(userDO, UserVO::new, (udo, uvo) -> {
//回调修改vo的role字段
uvo.setRole("role");
});
System.out.println(userVO);
UserVO userVO1 = BeanCopyUtil.copyProperties(userDO, UserVO::new);
System.out.println(userVO1);
List<UserDO> userList = Collections.singletonList(userDO);
List<UserVO> userVOList = BeanCopyUtil.copyListProperties(userList, UserVO::new, (udo, uvo) -> {
//回调修改vo的role字段
uvo.setRole("role list");
});
System.out.println(userVOList);
List<UserVO> userVOList1 = BeanCopyUtil.copyListProperties(userList, UserVO::new);
System.out.println(userVOList1);
}
}
//Output
UserVO(username=username1, password=null, email=asd@asd.com, role=role, roleName=)
UserVO(username=username1, password=null, email=asd@asd.com, role=null, roleName=)
[UserVO(username=username1, password=null, email=asd@asd.com, role=role list, roleName=)]
[UserVO(username=username1, password=null, email=asd@asd.com, role=null, roleName=)]
实际场景
比如实际使用时,对于分页数据从DO集合转换到VO集合,同时修改VO其中字段
default PageResult<?> page(QueryBase queryBase, ProjectRepository projectRepository) {
Pageable pageable = PageRequest.of(queryBase.getJpaPageIndex(), queryBase.getPageSize(), queryBase.getSort());
Page<TaskDO> pageResult = findAll(pageable);
List<TaskVO> result = BeanCopyUtil.copyListProperties(pageResult.getContent(), TaskVO::new, (taskDO, taskVO) -> {
String projectName = projectRepository.findById(taskDO.getProjectId()).map(ProjectDO::getName).orElse("");
taskVO.setProjectName(projectName);
});
return PageResult.build(result).setRecordsTotal(pageResult.getTotalElements());
}
回调接口
BeanCopyUtilCallBack
@FunctionalInterface
public interface BeanCopyUtilCallBack <S, T> {
/**
* 定义默认回调方法
* @param source 源数据
* @param target 目标数据
*/
void callBack(S source, T target);
}
Bean拷贝工具类代码
BeanCopyUtil
import org.springframework.beans.BeanUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
/**
* Bean拷贝工具类
*
* @author LoneKing
* @date 2020/10/22
*/
public class BeanCopyUtil extends BeanUtils {
/**
* 对象数据的拷贝
*
* @param source 数据源
* @param target 目标类::new(eg: UserVO::new)
* @param callBack 回调
* @param <S> 源数据类型
* @param <T> 目标数据类型
* @return 目标数据
*/
public static <S, T> T copyProperties(S source, Supplier<T> target, BeanCopyUtilCallBack<S, T> callBack) {
T t = target.get();
copyProperties(source, t);
if (callBack != null) {
// 回调
callBack.callBack(source, t);
}
return t;
}
/**
* 对象数据的拷贝
*
* @param source 数据源
* @param target 目标类::new(eg: UserVO::new)
* @param <S> 源数据类型
* @param <T> 目标数据类型
* @return 目标数据
*/
public static <S, T> T copyProperties(S source, Supplier<T> target) {
return copyProperties(source, target, (BeanCopyUtilCallBack<S, T>) null);
}
/**
* 集合数据的拷贝
*
* @param sources: 数据源
* @param target: 目标类::new(eg: UserVO::new)
* @param <S> 源数据类型
* @param <T> 目标数据类型
* @return List<T>
*/
public static <S, T> List<T> copyListProperties(List<S> sources, Supplier<T> target) {
return copyListProperties(sources, target, null);
}
/**
* 带回调函数的集合数据的拷贝(可自定义字段拷贝规则)
*
* @param sources: 数据源
* @param target: 目标类::new(eg: UserVO::new)
* @param callBack: 回调函数
* @param <S> 源数据类型
* @param <T> 目标数据类型
* @return List<T>
*/
public static <S, T> List<T> copyListProperties(List<S> sources, Supplier<T> target, BeanCopyUtilCallBack<S, T> callBack) {
List<T> list = new ArrayList<>(sources.size());
for (S source : sources) {
T t = target.get();
copyProperties(source, t);
if (callBack != null) {
// 回调
callBack.callBack(source, t);
}
list.add(t);
}
return list;
}
}