概述
实际的业务开发过程中,会面对BO, Entity, VO等各种对象。绝大部分场景下前端并不需要那么多的字段,那么当我们从数据库中查询到字段一般得到的是Entity,通常需要减少部分字段并赋值给VO,响应到前端。如果是单个Bean,可以非常方便的使用 BeanUtils.copyProperties(source, target);
来实现,但是对于列表的拷贝并没有提供相应的API,这时候就需要扩展 BeanUtils的功能。
代码实现
思考
public abstract class BeanUtils {
private static final ParameterNameDiscoverer parameterNameDiscoverer = new DefaultParameterNameDiscoverer();
private static final Set<Class<?>> unknownEditorTypes = Collections.newSetFromMap(new ConcurrentReferenceHashMap(64));
private static final Map<Class<?>, Object> DEFAULT_TYPE_VALUES;
public BeanUtils() {
}
......
public static boolean isSimpleValueType(Class<?> type) {
return Void.class != type && Void.TYPE != type && (ClassUtils.isPrimitiveOrWrapper(type) || Enum.class.isAssignableFrom(type) || CharSequence.class.isAssignableFrom(type) || Number.class.isAssignableFrom(type) || Date.class.isAssignableFrom(type) || Temporal.class.isAssignableFrom(type) || URI.class == type || URL.class == type || Locale.class == type || Class.class == type);
}
public static void copyProperties(Object source, Object target) throws BeansException {
copyProperties(source, target, (Class)null, (String[])null);
}
public static void copyProperties(Object source, Object target, Class<?> editable) throws BeansException {
copyProperties(source, target, editable, (String[])null);
}
......
}
BeanUtils
是一个抽象类,copyProperties
是静态方法,那么可以通过继承该类,并扩展自己的静态方法实现功能封装。
ExtendBeanUtils 扩展类
package com.lfc.shop.common.core.util;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;
/**
* 扩展BeanUtils
*
* 1. 拷贝列表元素的属性
*/
public class ExtendBeanUtils extends BeanUtils {
/**
* 简化版,无回调
*
* @param sources 待拷贝源列表
* @param target 目标列表元素的类
* @param <S> 数据源类
* @param <T> 目标类
* @return
*/
public static <S, T> List<T> copyListProperties(List<S> sources, Supplier<T> target) {
return copyListProperties(sources, target, null);
}
/**
*
* @param sources 待拷贝源列表
* @param target 目标列表元素的类
* @param callback 回调函数
* @param <S> 数据源类
* @param <T> 目标类
* @return
*/
public static <S, T> List<T> copyListProperties(List<S> sources, Supplier<T> target, ExtendBeanUtilsCallBack<S, T> callback) {
List<T> targetList = new ArrayList<>(sources.size());
if (!CollectionUtils.isEmpty(sources)) {
sources.forEach(source -> {
T t = target.get();
copyProperties(source, t);
if (Objects.nonNull(callback)) {
callback.callback(source, t);
}
targetList.add(t);
});
}
return targetList;
}
}
ExtendBeanUtilsCallback 回调接口
package com.lfc.shop.common.core.util;
@FunctionalInterface
public interface ExtendBeanUtilsCallback<S, T> {
void callback(S s, T t);
}
使用
无回调
仅仅需要拷贝对象的值
List<User> userList = commonService.getUserMapper().selectBatchIds(uidList);
if (userList != null) {
return ExtendBeanUtils.copyListProperties(userList, UserBaseVO::new);
}
return null;
有回调
回调函数,是在遍历赋值的过程中执行的,通常可以做一些数据判断再赋值的功能。这是我们项目中,清空身份证号的逻辑
List<User> userList = commonService.getUserMapper().selectBatchIds(uidList);
if (userList != null) {
return ExtendBeanUtils.copyListProperties(userList, UserBaseVO::new, (user, userBaseVO) -> {
System.out.println("拷贝:" + user + ", 到:" + userBaseVO);
if (StringUtils.isNoneBlank(user.getIdcard())) {
userBaseVO.setIdcard("");
}
});
}
return null;