这里使用的cglib是spring core包的。
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.cglib.core.Converter;
import org.springframework.core.convert.ConversionFailedException;
import org.springframework.core.convert.support.DefaultConversionService;
import java.util.*;
/**
* <p>使用Cglib高效的复制对象,不使用Spring的BeanCopy,支持类型互相转换。
* 如果转换失败会抛出{@link ConversionFailedException}异常。
* 这里的{@link org.springframework.cglib.beans.BeanCopier}
* 是spring-core包里集成的,不需要单独引入Cglib依赖包。
* <br/>注意:对象使用了Lombok注解时,不要有{@link Accessors}注解,否则无法复制。
* </p>
* <code>
*
* </code>
* @author chengjz
* @version 1.0
* @date 2020-04-01 14:46
*/
@Slf4j
public class FastCopy {
private static final DefaultConversionService conversionService = new DefaultConversionService();
public static final DefaultConverter converter = new DefaultConverter();
public static Map<String, BeanCopier> CACHE_MAP = new HashMap<>();
public static void addBothWayBeanCopy(Class<?> clz1, Class<?> clz2) {
addBothWayBeanCopy(clz1, clz2, true);
}
public static void addBothWayBeanCopy(Class<?> clz1, Class<?> clz2, boolean useConverter) {
CACHE_MAP.put(buildCacheKey(clz1, clz2), BeanCopier.create(clz1, clz2, useConverter));
CACHE_MAP.put(buildCacheKey(clz2, clz1), BeanCopier.create(clz2, clz1, useConverter));
}
/**
* 复制单个对象
* @param form 源对象
* @param to 复制的对象
* @param <T> 复制对象类型
* @return 复制对象实例
*/
public static <T> T copy(Object form, Class<T> to) {
return copy(form, to, converter);
}
/**
* 复制单个对象,自定义类型转换器,除非有必要,否则请使用{@link #copy(Object, Class)}方法
* @param form 源对象
* @param to 复制的对象
* @param converter 类型转换器
* @param <T> 复制对象类型
* @return 复制对象实例
*/
public static <T> T copy(Object form, Class<T> to, Converter converter) {
T targetSource = null;
try {
targetSource = to.newInstance();
} catch (Exception e) {
log.error("创建对象发生异常: ", e);
}
return copy(form, to, targetSource, converter);
}
/**
* 复制对象列表
* @param formList 源对象列表
* @param to 复制的对象
* @param <T> 复制对象类型
* @return 复制对象实例列表
*/
public static <F, T> List<T> listCopy(List<F> formList, Class<T> to) {
List<T> toList = new ArrayList<>(formList.size());
formList.forEach(v -> {
toList.add(copy(v, to));
});
return toList;
}
public static<T> T copy(Object form, Class<?> to, T targetSource, Converter converter) {
if (form == null) {
return targetSource;
}
final Class<?> formClass = form.getClass();
String cacheKey = buildCacheKey(formClass, to);
if (!CACHE_MAP.containsKey(cacheKey)) {
addBothWayBeanCopy(formClass, to);
}
CACHE_MAP.get(cacheKey).copy(form, targetSource, converter);
return targetSource;
}
private static String buildCacheKey(Class<?> clz1, Class<?> clz2) {
return clz1.getName() + "_" + clz2.getName();
}
public static class DefaultConverter implements Converter {
@Override
public Object convert(Object source, Class target, Object context) {
if (source == null) {
return null;
}
if (isJavaClass(target) || source instanceof Collection<?> || source instanceof Map<?,?>) {
return conversionService.convert(source, target);
}
return copy(source, target);
}
}
public static boolean isJavaClass(Class<?> clz) {
return clz != null && clz.getClassLoader() == null;
}
}