diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/BeanDesc.java b/hutool-core/src/main/java/cn/hutool/core/bean/BeanDesc.java index 976f40d29..cb23a98d3 100644 --- a/hutool-core/src/main/java/cn/hutool/core/bean/BeanDesc.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/BeanDesc.java @@ -181,7 +181,8 @@ public class BeanDesc implements Serializable { prop.setter = propIgnoreCase.setter; } } - + // 所有属性完成填充后的初始化逻辑 + prop.initialize(); return prop; } diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/PropDesc.java b/hutool-core/src/main/java/cn/hutool/core/bean/PropDesc.java index 811ce70f3..65e5560c3 100644 --- a/hutool-core/src/main/java/cn/hutool/core/bean/PropDesc.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/PropDesc.java @@ -36,6 +36,22 @@ public class PropDesc { * Setter方法 */ protected Method setter; + /** + * get方法或字段上有无transient关键字和@Transient注解 + */ + private boolean transientForGet; + /** + * set方法或字段上有无transient关键字和@Transient注解 + */ + private boolean transientForSet; + /** + * 检查set方法和字段有无@PropIgnore注解 + */ + private boolean ignoreGet; + /** + * 检查set方法和字段有无@PropIgnore注解 + */ + private boolean ignoreSet; /** * 构造
@@ -51,6 +67,17 @@ public class PropDesc { this.setter = ClassUtil.setAccessible(setter); } + /** + * 在对象的所有属性设置完成后,执行初始化逻辑。 + *

+ * 预先计算transient关键字和@Transient注解、{@link PropIgnore}注解信息 + */ + public void initialize() { + transientForGet = isTransientForGet(); + transientForSet = isTransientForSet(); + ignoreGet = isIgnoreGet(); + ignoreSet = isIgnoreSet(); + } /** * 获取字段名,如果存在Alias注解,读取注解的值作为名称 * @@ -137,12 +164,12 @@ public class PropDesc { } // 检查transient关键字和@Transient注解 - if (checkTransient && isTransientForGet()) { + if (checkTransient && transientForGet) { return false; } // 检查@PropIgnore注解 - return false == isIgnoreGet(); + return false == ignoreGet; } /** @@ -207,12 +234,12 @@ public class PropDesc { } // 检查transient关键字和@Transient注解 - if (checkTransient && isTransientForSet()) { + if (checkTransient && transientForSet) { return false; } // 检查@PropIgnore注解 - return false == isIgnoreSet(); + return false == ignoreSet; } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/bean/copier/CopyOptions.java b/hutool-core/src/main/java/cn/hutool/core/bean/copier/CopyOptions.java index bdb97c1db..d7e479772 100755 --- a/hutool-core/src/main/java/cn/hutool/core/bean/copier/CopyOptions.java +++ b/hutool-core/src/main/java/cn/hutool/core/bean/copier/CopyOptions.java @@ -9,6 +9,7 @@ import cn.hutool.core.lang.Editor; import cn.hutool.core.lang.func.Func1; import cn.hutool.core.lang.func.LambdaUtil; import cn.hutool.core.util.ArrayUtil; +import cn.hutool.core.util.ClassUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; @@ -91,6 +92,14 @@ public class CopyOptions implements Serializable { return null; } + // 快速处理简单值类型的转换 + if (type instanceof Class){ + Class targetType = (Class) type; + if (ClassUtil.isSimpleValueType(targetType) && targetType.isInstance(value)) { + return targetType.cast(value); + } + } + if (value instanceof IJSONTypeConverter) { return ((IJSONTypeConverter) value).toBean(ObjectUtil.defaultIfNull(type, Object.class)); } diff --git a/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java index cbcc80b13..c52d6c18e 100755 --- a/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/bean/BeanUtilTest.java @@ -5,6 +5,8 @@ import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.bean.copier.ValueProvider; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.date.StopWatch; +import cn.hutool.core.lang.Console; import cn.hutool.core.lang.Dict; import cn.hutool.core.map.MapBuilder; import cn.hutool.core.map.MapUtil; @@ -707,6 +709,37 @@ public class BeanUtilTest { } + @Test + public void copyLargeListTest(){ + final SubPerson person = new SubPerson(); + person.setName("测试A11"); + person.setAge(14); + person.setOpenid("11213232"); + + person.setId(UUID.randomUUID()); + person.setSubName("sub名字"); + person.setSlow(true); + person.setDate(LocalDateTime.now()); + person.setDate2(LocalDate.now()); + + final List list = new ArrayList<>(); + CollUtil.padRight(list, 1000, person); + + // 预先构建一次缓存,防止干扰 + BeanUtil.copyProperties(person, new SubPerson2()); + // org.springframework.beans.BeanUtils.copyProperties(new SubPerson(), new SubPerson2()); + + Console.log("copy bean size: {}\n", list.size()); + final StopWatch stopWatch = new StopWatch(); + stopWatch.start("BeanUtil#copyToList"); + List copyList = BeanUtil.copyToList(list, SubPerson2.class); + // list.forEach(item -> org.springframework.beans.BeanUtils.copyProperties(item, new SubPerson2())); + stopWatch.stop(); + Console.log(stopWatch.prettyPrint()); + assertEquals(copyList.size(),list.size()); + } + + @Test public void toMapTest() { // 测试转map的时候返回key