From 71d1fcbf5aa3ed3ca2dc267959dfc71635a69bfe Mon Sep 17 00:00:00 2001 From: hongruiz Date: Sat, 29 Aug 2020 04:34:32 +0800 Subject: [PATCH] fix bug and improve --- .../hutool/extra/cglib/BeanCopierCache.java | 33 ++++++-- .../java/cn/hutool/extra/cglib/CglibUtil.java | 82 ++++++++++++++++++- 2 files changed, 103 insertions(+), 12 deletions(-) diff --git a/hutool-extra/src/main/java/cn/hutool/extra/cglib/BeanCopierCache.java b/hutool-extra/src/main/java/cn/hutool/extra/cglib/BeanCopierCache.java index 7378b9090..2573bd7d4 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/cglib/BeanCopierCache.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/cglib/BeanCopierCache.java @@ -1,11 +1,9 @@ package cn.hutool.extra.cglib; import cn.hutool.core.lang.SimpleCache; -import cn.hutool.core.lang.func.Func0; import cn.hutool.core.util.StrUtil; import net.sf.cglib.beans.BeanCopier; - -import java.beans.PropertyDescriptor; +import net.sf.cglib.core.Converter; /** * BeanCopier属性缓存
@@ -15,20 +13,39 @@ import java.beans.PropertyDescriptor; * @since 5.4.1 */ public enum BeanCopierCache { + /** + * BeanCopier属性缓存单例 + */ INSTANCE; private final SimpleCache cache = new SimpleCache<>(); /** - * 获得属性名和{@link PropertyDescriptor}Map映射 + * 获得类与转换器生成的key在{@link BeanCopier}的Map中对应的元素 * * @param srcClass 源Bean的类 * @param targetClass 目标Bean的类 - * @param supplier 缓存对象产生函数 - * @return 属性名和{@link PropertyDescriptor}Map映射 + * @param converter 转换器 + * @return Map中对应的BeanCopier * @since 5.4.1 */ - public BeanCopier get(Class srcClass, Class targetClass, Func0 supplier) { - return this.cache.get(StrUtil.format("{}_{}", srcClass.getName(), srcClass.getName()), supplier); + public BeanCopier get(Class srcClass, Class targetClass, Converter converter) { + 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()); } } diff --git a/hutool-extra/src/main/java/cn/hutool/extra/cglib/CglibUtil.java b/hutool-extra/src/main/java/cn/hutool/extra/cglib/CglibUtil.java index cc0e56b0d..d4f8a637e 100644 --- a/hutool-extra/src/main/java/cn/hutool/extra/cglib/CglibUtil.java +++ b/hutool-extra/src/main/java/cn/hutool/extra/cglib/CglibUtil.java @@ -6,6 +6,11 @@ import net.sf.cglib.beans.BeanCopier; import net.sf.cglib.beans.BeanMap; 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工具类 * @@ -22,6 +27,7 @@ public class CglibUtil { * @param source 源bean对象 * @param targetClass 目标bean类,自动实例化此对象 * @return 目标对象 + * @since 5.4.1 */ public static T copy(Object source, Class targetClass) { return copy(source, targetClass, null); @@ -36,10 +42,11 @@ public class CglibUtil { * @param targetClass 目标bean类,自动实例化此对象 * @param converter 转换器,无需可传{@code null} * @return 目标对象 + * @since 5.4.1 */ public static T copy(Object source, Class targetClass, Converter converter) { final T target = ReflectUtil.newInstanceIfPossible(targetClass); - copy(source, target); + copy(source, target, converter); return target; } @@ -48,6 +55,7 @@ public class CglibUtil { * * @param source 源bean对象 * @param target 目标bean对象 + * @since 5.4.1 */ public static void copy(Object source, Object target) { copy(source, target, null); @@ -66,18 +74,84 @@ public class CglibUtil { final Class sourceClass = source.getClass(); final Class targetClass = target.getClass(); - final BeanCopier beanCopier = BeanCopierCache.INSTANCE.get( - sourceClass, targetClass, - () -> BeanCopier.create(sourceClass, targetClass, null != converter)); + final BeanCopier beanCopier = BeanCopierCache.INSTANCE.get(sourceClass, targetClass, converter); beanCopier.copy(source, target, converter); } + /** + * 拷贝List Bean对象属性 + * + * @param source 源bean对象list + * @param target 目标bean对象 + * @param 源bean类型 + * @param 目标bean类型 + * @return 目标bean对象list + * @since 5.4.1 + */ + public static List copyList(List source, Supplier target) { + return copyList(source, target, null, null); + } + + /** + * 拷贝List Bean对象属性 + * + * @param source 源bean对象list + * @param target 目标bean对象 + * @param converter 转换器,无需可传{@code null} + * @param 源bean类型 + * @param 目标bean类型 + * @return 目标bean对象list + * @since 5.4.1 + */ + public static List copyList(List source, Supplier target, Converter converter) { + return copyList(source, target, converter, null); + } + + /** + * 拷贝List Bean对象属性 + * + * @param source 源bean对象list + * @param target 目标bean对象 + * @param callback 回调对象 + * @param 源bean类型 + * @param 目标bean类型 + * @return 目标bean对象list + * @since 5.4.1 + */ + public static List copyList(List source, Supplier target, BiConsumer callback) { + return copyList(source, target, null, callback); + } + + /** + * 拷贝List Bean对象属性 + * + * @param source 源bean对象list + * @param target 目标bean对象 + * @param converter 转换器,无需可传{@code null} + * @param callback 回调对象 + * @param 源bean类型 + * @param 目标bean类型 + * @return 目标bean对象list + * @since 5.4.1 + */ + public static List copyList(List source, Supplier target, Converter converter, BiConsumer 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 * * @param bean Bean对象 * @return {@link BeanMap} + * @since 5.4.1 */ public static BeanMap toMap(Object bean) { return BeanMap.create(bean);