package com.example.test.utils;
import net.sf.cglib.beans.BeanMap; import org.springframework.cglib.beans.BeanCopier; import org.springframework.objenesis.ObjenesisStd;
import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap;
/**
* @author bian lei
* @version 1.0
* @date 2020/4/23 18:55
*/
public class BeanCopierUtil {
private static ThreadLocal<ObjenesisStd> objenesisStdThreadLocal = ThreadLocal.withInitial(ObjenesisStd::new);
private static ConcurrentHashMap<Class<?>, ConcurrentHashMap<Class<?>, BeanCopier>> cache = new ConcurrentHashMap<>();
public static <T> T copy(Object source, Class<T> target) {
return copy(source, objenesisStdThreadLocal.get().newInstance(target));
}
private static <T> T copy(Object source, T target) {
BeanCopier beanCopier = getCacheBeanCopier(source.getClass(), target.getClass());
beanCopier.copy(source, target, null);
return target;
}
/**
* 普通copy 集合
*
* @param sources
* @param target
* @param <T>
* @return
*/
public static <T> List<T> copyList(List<?> sources, Class<T> target) {
if (sources.isEmpty()) {
return Collections.emptyList();
}
ArrayList<T> list = new ArrayList<>(sources.size());
ObjenesisStd objenesisStd = objenesisStdThreadLocal.get();
for (Object source : sources) {
if (source == null) {
return new ArrayList<>();
}
T newInstance = objenesisStd.newInstance(target);
BeanCopier beanCopier = getCacheBeanCopier(source.getClass(), target);
beanCopier.copy(source, newInstance, null);
list.add(newInstance);
}
return list;
}
/**
* 解决属性名相同、类型不同copy
*
* @param sources
* @param target
* @param <T>
* @return
*/
// public static <T> List<T> depthCoptList(List<?> sources, Class<T> target) {
// if (sources.isEmpty()) {
// return Collections.emptyList();
// }
// for (Object source : sources) {
// source.getClass().getDeclaredFields();
// }
// return;
// }
public static <T> T mapToBean(Map<?, ?> source, Class<T> target) {
T bean = objenesisStdThreadLocal.get().newInstance(target);
BeanMap beanMap = BeanMap.create(bean);
beanMap.putAll(source);
return bean;
}
public static <T> Map<?, ?> beanToMap(T source) {
return BeanMap.create(source);
}
/**
* 带缓存
*
* @param source
* @param target
* @param <S>
* @param <T>
* @return
*/
private static <S, T> BeanCopier getCacheBeanCopier(Class<S> source, Class<T> target) {
ConcurrentHashMap<Class<?>, BeanCopier> copierConcurrentHashMap = cache.computeIfAbsent(source, aClass -> new ConcurrentHashMap<>(16));
return copierConcurrentHashMap.computeIfAbsent(target, aClass -> BeanCopier.create(source, target, false));
}
}
如果想规避属性名相同,类型不同的坑,就需要用到反射,又会影响应性能