fix bug and improve

This commit is contained in:
hongruiz 2020-08-29 04:34:32 +08:00
parent 32ff87a682
commit 71d1fcbf5a
2 changed files with 103 additions and 12 deletions

View File

@ -1,11 +1,9 @@
package cn.hutool.extra.cglib; package cn.hutool.extra.cglib;
import cn.hutool.core.lang.SimpleCache; import cn.hutool.core.lang.SimpleCache;
import cn.hutool.core.lang.func.Func0;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import net.sf.cglib.beans.BeanCopier; import net.sf.cglib.beans.BeanCopier;
import net.sf.cglib.core.Converter;
import java.beans.PropertyDescriptor;
/** /**
* BeanCopier属性缓存<br> * BeanCopier属性缓存<br>
@ -15,20 +13,39 @@ import java.beans.PropertyDescriptor;
* @since 5.4.1 * @since 5.4.1
*/ */
public enum BeanCopierCache { public enum BeanCopierCache {
/**
* BeanCopier属性缓存单例
*/
INSTANCE; INSTANCE;
private final SimpleCache<String, BeanCopier> cache = new SimpleCache<>(); private final SimpleCache<String, BeanCopier> cache = new SimpleCache<>();
/** /**
* 获得属性名和{@link PropertyDescriptor}Map映射 * 获得类与转换器生成的key在{@link BeanCopier}的Map中对应的元素
* *
* @param srcClass 源Bean的类 * @param srcClass 源Bean的类
* @param targetClass 目标Bean的类 * @param targetClass 目标Bean的类
* @param supplier 缓存对象产生函数 * @param converter 转换器
* @return 属性名和{@link PropertyDescriptor}Map映射 * @return Map中对应的BeanCopier
* @since 5.4.1 * @since 5.4.1
*/ */
public BeanCopier get(Class<?> srcClass, Class<?> targetClass, Func0<BeanCopier> supplier) { public BeanCopier get(Class<?> srcClass, Class<?> targetClass, Converter converter) {
return this.cache.get(StrUtil.format("{}_{}", srcClass.getName(), srcClass.getName()), supplier); String key = genKey(srcClass, targetClass, converter);
return cache.get(key, () -> BeanCopier.create(srcClass, targetClass, converter != null));
}
/**
* 获得类与转换器生成的key
*
* @param srcClass 源Bean的类
* @param targetClass 目标Bean的类
* @param converter 转换器
* @return 属性名和Map映射的key
* @since 5.4.1
*/
private String genKey(Class<?> srcClass, Class<?> targetClass, Converter converter) {
return converter == null ? StrUtil.format("{}#{}", srcClass.getName(), targetClass.getName())
: StrUtil.format("{}#{}#{}", srcClass.getName(), targetClass.getName(), converter.getClass().getName());
} }
} }

View File

@ -6,6 +6,11 @@ import net.sf.cglib.beans.BeanCopier;
import net.sf.cglib.beans.BeanMap; import net.sf.cglib.beans.BeanMap;
import net.sf.cglib.core.Converter; import net.sf.cglib.core.Converter;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;
/** /**
* Cglib工具类 * Cglib工具类
* *
@ -22,6 +27,7 @@ public class CglibUtil {
* @param source 源bean对象 * @param source 源bean对象
* @param targetClass 目标bean类自动实例化此对象 * @param targetClass 目标bean类自动实例化此对象
* @return 目标对象 * @return 目标对象
* @since 5.4.1
*/ */
public static <T> T copy(Object source, Class<T> targetClass) { public static <T> T copy(Object source, Class<T> targetClass) {
return copy(source, targetClass, null); return copy(source, targetClass, null);
@ -36,10 +42,11 @@ public class CglibUtil {
* @param targetClass 目标bean类自动实例化此对象 * @param targetClass 目标bean类自动实例化此对象
* @param converter 转换器无需可传{@code null} * @param converter 转换器无需可传{@code null}
* @return 目标对象 * @return 目标对象
* @since 5.4.1
*/ */
public static <T> T copy(Object source, Class<T> targetClass, Converter converter) { public static <T> T copy(Object source, Class<T> targetClass, Converter converter) {
final T target = ReflectUtil.newInstanceIfPossible(targetClass); final T target = ReflectUtil.newInstanceIfPossible(targetClass);
copy(source, target); copy(source, target, converter);
return target; return target;
} }
@ -48,6 +55,7 @@ public class CglibUtil {
* *
* @param source 源bean对象 * @param source 源bean对象
* @param target 目标bean对象 * @param target 目标bean对象
* @since 5.4.1
*/ */
public static void copy(Object source, Object target) { public static void copy(Object source, Object target) {
copy(source, target, null); copy(source, target, null);
@ -66,18 +74,84 @@ public class CglibUtil {
final Class<?> sourceClass = source.getClass(); final Class<?> sourceClass = source.getClass();
final Class<?> targetClass = target.getClass(); final Class<?> targetClass = target.getClass();
final BeanCopier beanCopier = BeanCopierCache.INSTANCE.get( final BeanCopier beanCopier = BeanCopierCache.INSTANCE.get(sourceClass, targetClass, converter);
sourceClass, targetClass,
() -> BeanCopier.create(sourceClass, targetClass, null != converter));
beanCopier.copy(source, target, converter); beanCopier.copy(source, target, converter);
} }
/**
* 拷贝List Bean对象属性
*
* @param source 源bean对象list
* @param target 目标bean对象
* @param <S> 源bean类型
* @param <T> 目标bean类型
* @return 目标bean对象list
* @since 5.4.1
*/
public static <S, T> List<T> copyList(List<S> source, Supplier<T> target) {
return copyList(source, target, null, null);
}
/**
* 拷贝List Bean对象属性
*
* @param source 源bean对象list
* @param target 目标bean对象
* @param converter 转换器无需可传{@code null}
* @param <S> 源bean类型
* @param <T> 目标bean类型
* @return 目标bean对象list
* @since 5.4.1
*/
public static <S, T> List<T> copyList(List<S> source, Supplier<T> target, Converter converter) {
return copyList(source, target, converter, null);
}
/**
* 拷贝List Bean对象属性
*
* @param source 源bean对象list
* @param target 目标bean对象
* @param callback 回调对象
* @param <S> 源bean类型
* @param <T> 目标bean类型
* @return 目标bean对象list
* @since 5.4.1
*/
public static <S, T> List<T> copyList(List<S> source, Supplier<T> target, BiConsumer<S, T> callback) {
return copyList(source, target, null, callback);
}
/**
* 拷贝List Bean对象属性
*
* @param source 源bean对象list
* @param target 目标bean对象
* @param converter 转换器无需可传{@code null}
* @param callback 回调对象
* @param <S> 源bean类型
* @param <T> 目标bean类型
* @return 目标bean对象list
* @since 5.4.1
*/
public static <S, T> List<T> copyList(List<S> source, Supplier<T> target, Converter converter, BiConsumer<S, T> callback) {
return source.stream().map(s -> {
T t = target.get();
copy(source, t, converter);
if (callback != null) {
callback.accept(s, t);
}
return t;
}).collect(Collectors.toList());
}
/** /**
* 将Bean转换为Map * 将Bean转换为Map
* *
* @param bean Bean对象 * @param bean Bean对象
* @return {@link BeanMap} * @return {@link BeanMap}
* @since 5.4.1
*/ */
public static BeanMap toMap(Object bean) { public static BeanMap toMap(Object bean) {
return BeanMap.create(bean); return BeanMap.create(bean);