Browse Source

fix bug and improve

hongruiz 5 years ago
parent
commit
71d1fcbf5a

+ 25 - 8
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属性缓存<br>
@@ -15,20 +13,39 @@ import java.beans.PropertyDescriptor;
  * @since 5.4.1
  */
 public enum BeanCopierCache {
+	/**
+	 * BeanCopier属性缓存单例
+	 */
 	INSTANCE;
 
 	private final SimpleCache<String, BeanCopier> cache = new SimpleCache<>();
 
 	/**
-	 * 获得属性名和{@link PropertyDescriptor}Map映射
+	 * 获得类与转换器生成的key在{@link BeanCopier}的Map中对应的元素
+	 *
+	 * @param srcClass    源Bean的类
+	 * @param targetClass 目标Bean的类
+	 * @param converter   转换器
+	 * @return Map中对应的BeanCopier
+	 * @since 5.4.1
+	 */
+	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 supplier    缓存对象产生函数
-	 * @return 属性名和{@link PropertyDescriptor}Map映射
+	 * @param converter   转换器
+	 * @return 属性名和Map映射的key
 	 * @since 5.4.1
 	 */
-	public BeanCopier get(Class<?> srcClass, Class<?> targetClass, Func0<BeanCopier> supplier) {
-		return this.cache.get(StrUtil.format("{}_{}", srcClass.getName(), srcClass.getName()), supplier);
+	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());
 	}
 }

+ 78 - 4
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> T copy(Object source, Class<T> 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> T copy(Object source, Class<T> 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 <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
 	 *
 	 * @param bean Bean对象
 	 * @return {@link BeanMap}
+	 * @since 5.4.1
 	 */
 	public static BeanMap toMap(Object bean) {
 		return BeanMap.create(bean);