From dbcf9eb3f3c5331e2c5631f837072fec27c9aae8 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 10 Nov 2023 21:25:55 +0800 Subject: [PATCH] add object creator --- .../hutool/core/reflect/ConstructorUtil.java | 67 +--------- .../reflect/creator/DefaultObjectCreator.java | 74 +++++++++++ .../core/reflect/creator/ObjectCreator.java | 29 +++++ .../creator/PossibleObjectCreator.java | 121 ++++++++++++++++++ .../core/reflect/creator/package-info.java | 19 +++ 5 files changed, 250 insertions(+), 60 deletions(-) create mode 100644 hutool-core/src/main/java/org/dromara/hutool/core/reflect/creator/DefaultObjectCreator.java create mode 100644 hutool-core/src/main/java/org/dromara/hutool/core/reflect/creator/ObjectCreator.java create mode 100644 hutool-core/src/main/java/org/dromara/hutool/core/reflect/creator/PossibleObjectCreator.java create mode 100644 hutool-core/src/main/java/org/dromara/hutool/core/reflect/creator/package-info.java diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/reflect/ConstructorUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/reflect/ConstructorUtil.java index 40a7ac9f5..570a5f068 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/reflect/ConstructorUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/reflect/ConstructorUtil.java @@ -12,17 +12,13 @@ package org.dromara.hutool.core.reflect; -import org.dromara.hutool.core.classloader.ClassLoaderUtil; import org.dromara.hutool.core.exception.HutoolException; import org.dromara.hutool.core.lang.Assert; import org.dromara.hutool.core.map.WeakConcurrentMap; -import org.dromara.hutool.core.reflect.lookup.LookupUtil; -import org.dromara.hutool.core.reflect.method.MethodHandleUtil; +import org.dromara.hutool.core.reflect.creator.DefaultObjectCreator; +import org.dromara.hutool.core.reflect.creator.PossibleObjectCreator; -import java.lang.invoke.MethodHandle; -import java.lang.reflect.Array; import java.lang.reflect.Constructor; -import java.util.*; /** * 反射中{@link Constructor}构造工具类,包括获取构造类和通过构造实例化对象相关工具 @@ -99,8 +95,9 @@ public class ConstructorUtil { * @return 对象 * @throws HutoolException 包装各类异常 */ + @SuppressWarnings("unchecked") public static T newInstance(final String clazz) throws HutoolException { - return newInstance(ClassLoaderUtil.loadClass(clazz)); + return (T) DefaultObjectCreator.of(clazz).create(); } /** @@ -113,9 +110,7 @@ public class ConstructorUtil { * @throws HutoolException 包装各类异常 */ public static T newInstance(final Class clazz, final Object... params) throws HutoolException { - final Class[] paramTypes = ClassUtil.getClasses(params); - final MethodHandle constructor = LookupUtil.findConstructor(clazz, paramTypes); - return MethodHandleUtil.invokeHandle(constructor, params); + return DefaultObjectCreator.of(clazz, params).create(); } /** @@ -133,55 +128,7 @@ public class ConstructorUtil { * @param type 被构造的类 * @return 构造后的对象,构造失败返回{@code null} */ - @SuppressWarnings("unchecked") - public static T newInstanceIfPossible(Class type) { - Assert.notNull(type); - - // 原始类型 - if (type.isPrimitive()) { - return (T) ClassUtil.getPrimitiveDefaultValue(type); - } - - // 某些特殊接口的实例化按照默认实现进行 - if (type.isAssignableFrom(AbstractMap.class)) { - type = (Class) HashMap.class; - } else if (type.isAssignableFrom(List.class)) { - type = (Class) ArrayList.class; - } else if (type.isAssignableFrom(Set.class)) { - type = (Class) HashSet.class; - } - - try { - return newInstance(type); - } catch (final Exception e) { - // ignore - // 默认构造不存在的情况下查找其它构造 - } - - // 枚举 - if (type.isEnum()) { - return type.getEnumConstants()[0]; - } - - // 数组 - if (type.isArray()) { - return (T) Array.newInstance(type.getComponentType(), 0); - } - - final Constructor[] constructors = getConstructors(type); - Class[] parameterTypes; - for (final Constructor constructor : constructors) { - parameterTypes = constructor.getParameterTypes(); - if (0 == parameterTypes.length) { - continue; - } - ReflectUtil.setAccessible(constructor); - try { - return constructor.newInstance(ClassUtil.getDefaultValues(parameterTypes)); - } catch (final Exception ignore) { - // 构造出错时继续尝试下一种构造方式 - } - } - return null; + public static T newInstanceIfPossible(final Class type) { + return PossibleObjectCreator.of(type).create(); } } diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/reflect/creator/DefaultObjectCreator.java b/hutool-core/src/main/java/org/dromara/hutool/core/reflect/creator/DefaultObjectCreator.java new file mode 100644 index 000000000..4a037492b --- /dev/null +++ b/hutool-core/src/main/java/org/dromara/hutool/core/reflect/creator/DefaultObjectCreator.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2023. looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * https://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +package org.dromara.hutool.core.reflect.creator; + +import org.dromara.hutool.core.classloader.ClassLoaderUtil; +import org.dromara.hutool.core.lang.Assert; +import org.dromara.hutool.core.reflect.ClassUtil; +import org.dromara.hutool.core.reflect.lookup.LookupUtil; +import org.dromara.hutool.core.reflect.method.MethodHandleUtil; + +import java.lang.invoke.MethodHandle; + +/** + * 默认对象实例化器
+ * 通过传入对象类型和构造函数的参数,调用对应的构造方法创建对象。 + * + * @param 对象类型 + */ +public class DefaultObjectCreator implements ObjectCreator { + + /** + * 创建默认的对象实例化器 + * + * @param fullClassName 类名全程 + * @param 对象类型 + * @return DefaultObjectCreator + */ + public static DefaultObjectCreator of(final String fullClassName) { + return of(ClassLoaderUtil.loadClass(fullClassName)); + } + + /** + * 创建默认的对象实例化器 + * + * @param clazz 实例化的类 + * @param params 构造参数,无参数空 + * @param 对象类型 + * @return DefaultObjectCreator + */ + public static DefaultObjectCreator of(final Class clazz, final Object... params) { + return new DefaultObjectCreator<>(clazz, params); + } + + final MethodHandle constructor; + final Object[] params; + + /** + * 构造 + * + * @param clazz 实例化的类 + * @param params 构造参数,无参数空 + */ + public DefaultObjectCreator(final Class clazz, final Object... params) { + final Class[] paramTypes = ClassUtil.getClasses(params); + this.constructor = LookupUtil.findConstructor(clazz, paramTypes); + Assert.notNull(this.constructor, "Constructor not found!"); + this.params = params; + } + + @Override + public T create() { + return MethodHandleUtil.invokeHandle(constructor, params); + } +} diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/reflect/creator/ObjectCreator.java b/hutool-core/src/main/java/org/dromara/hutool/core/reflect/creator/ObjectCreator.java new file mode 100644 index 000000000..08f7fc0a1 --- /dev/null +++ b/hutool-core/src/main/java/org/dromara/hutool/core/reflect/creator/ObjectCreator.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2023. looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * https://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +package org.dromara.hutool.core.reflect.creator; + +/** + * 对象创建器,用于自定义创建指定类型、指定参数的对象
+ * 也叫对象初始化器。 + * + * @param 对象类型 + * @since 6.0.0 + */ +public interface ObjectCreator { + /** + * 创建对象 + * + * @return 对象 + */ + T create(); +} diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/reflect/creator/PossibleObjectCreator.java b/hutool-core/src/main/java/org/dromara/hutool/core/reflect/creator/PossibleObjectCreator.java new file mode 100644 index 000000000..8e66d59c9 --- /dev/null +++ b/hutool-core/src/main/java/org/dromara/hutool/core/reflect/creator/PossibleObjectCreator.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2023. looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * https://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +package org.dromara.hutool.core.reflect.creator; + +import org.dromara.hutool.core.lang.Assert; +import org.dromara.hutool.core.reflect.ClassUtil; +import org.dromara.hutool.core.reflect.ConstructorUtil; +import org.dromara.hutool.core.reflect.ReflectUtil; + +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.util.*; + +/** + * 尝试方式对象实例化器
+ * 通过判断类型或调用可能的构造,构建对象,支持: + *
    + *
  • 原始类型
  • + *
  • 接口或抽象类型
  • + *
  • 枚举
  • + *
  • 数组
  • + *
  • 使用默认参数的构造方法
  • + *
+ *

+ * 对于接口或抽象类型,构造其默认实现: + *

+ *     Map       -》 HashMap
+ *     Collction -》 ArrayList
+ *     List      -》 ArrayList
+ *     Set       -》 HashSet
+ * 
+ * + * @param 对象类型 + */ +public class PossibleObjectCreator implements ObjectCreator { + + /** + * 创建默认的对象实例化器 + * + * @param clazz 实例化的类 + * @param 对象类型 + * @return DefaultObjectCreator + */ + public static PossibleObjectCreator of(final Class clazz) { + return new PossibleObjectCreator<>(clazz); + } + + final Class clazz; + + /** + * 构造 + * + * @param clazz 实例化的类 + */ + public PossibleObjectCreator(final Class clazz) { + this.clazz = Assert.notNull(clazz); + } + + @Override + @SuppressWarnings("unchecked") + public T create() { + Class type = this.clazz; + + // 原始类型 + if (type.isPrimitive()) { + return (T) ClassUtil.getPrimitiveDefaultValue(type); + } + + // 某些特殊接口的实例化按照默认实现进行 + if (type.isAssignableFrom(AbstractMap.class)) { + type = (Class) HashMap.class; + } else if (type.isAssignableFrom(List.class)) { + type = (Class) ArrayList.class; + } else if (type.isAssignableFrom(Set.class)) { + type = (Class) HashSet.class; + } + + try { + return DefaultObjectCreator.of(type).create(); + } catch (final Exception e) { + // ignore + // 默认构造不存在的情况下查找其它构造 + } + + // 枚举 + if (type.isEnum()) { + return type.getEnumConstants()[0]; + } + + // 数组 + if (type.isArray()) { + return (T) Array.newInstance(type.getComponentType(), 0); + } + + final Constructor[] constructors = ConstructorUtil.getConstructors(type); + Class[] parameterTypes; + for (final Constructor constructor : constructors) { + parameterTypes = constructor.getParameterTypes(); + if (0 == parameterTypes.length) { + continue; + } + ReflectUtil.setAccessible(constructor); + try { + return constructor.newInstance(ClassUtil.getDefaultValues(parameterTypes)); + } catch (final Exception ignore) { + // 构造出错时继续尝试下一种构造方式 + } + } + return null; + } +} diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/reflect/creator/package-info.java b/hutool-core/src/main/java/org/dromara/hutool/core/reflect/creator/package-info.java new file mode 100644 index 000000000..d03f6d166 --- /dev/null +++ b/hutool-core/src/main/java/org/dromara/hutool/core/reflect/creator/package-info.java @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023. looly(loolly@aliyun.com) + * Hutool is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * https://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ + +/** + * 对象实例化器,对象创建器 + * + * @author looly + * @since 6.0.0 + */ +package org.dromara.hutool.core.reflect.creator;