add object creator

This commit is contained in:
Looly 2023-11-10 21:25:55 +08:00
parent 659af4d5f2
commit dbcf9eb3f3
5 changed files with 250 additions and 60 deletions

View File

@ -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> 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> T newInstance(final Class<T> 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> T newInstanceIfPossible(Class<T> type) {
Assert.notNull(type);
// 原始类型
if (type.isPrimitive()) {
return (T) ClassUtil.getPrimitiveDefaultValue(type);
}
// 某些特殊接口的实例化按照默认实现进行
if (type.isAssignableFrom(AbstractMap.class)) {
type = (Class<T>) HashMap.class;
} else if (type.isAssignableFrom(List.class)) {
type = (Class<T>) ArrayList.class;
} else if (type.isAssignableFrom(Set.class)) {
type = (Class<T>) 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<T>[] constructors = getConstructors(type);
Class<?>[] parameterTypes;
for (final Constructor<T> 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> T newInstanceIfPossible(final Class<T> type) {
return PossibleObjectCreator.of(type).create();
}
}

View File

@ -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;
/**
* 默认对象实例化器<br>
* 通过传入对象类型和构造函数的参数调用对应的构造方法创建对象
*
* @param <T> 对象类型
*/
public class DefaultObjectCreator<T> implements ObjectCreator<T> {
/**
* 创建默认的对象实例化器
*
* @param fullClassName 类名全程
* @param <T> 对象类型
* @return DefaultObjectCreator
*/
public static <T> DefaultObjectCreator<T> of(final String fullClassName) {
return of(ClassLoaderUtil.loadClass(fullClassName));
}
/**
* 创建默认的对象实例化器
*
* @param clazz 实例化的类
* @param params 构造参数无参数空
* @param <T> 对象类型
* @return DefaultObjectCreator
*/
public static <T> DefaultObjectCreator<T> of(final Class<T> clazz, final Object... params) {
return new DefaultObjectCreator<>(clazz, params);
}
final MethodHandle constructor;
final Object[] params;
/**
* 构造
*
* @param clazz 实例化的类
* @param params 构造参数无参数空
*/
public DefaultObjectCreator(final Class<T> 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);
}
}

View File

@ -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;
/**
* 对象创建器用于自定义创建指定类型指定参数的对象<br>
* 也叫对象初始化器
*
* @param <T> 对象类型
* @since 6.0.0
*/
public interface ObjectCreator<T> {
/**
* 创建对象
*
* @return 对象
*/
T create();
}

View File

@ -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.*;
/**
* 尝试方式对象实例化器<br>
* 通过判断类型或调用可能的构造构建对象支持
* <ul>
* <li>原始类型</li>
* <li>接口或抽象类型</li>
* <li>枚举</li>
* <li>数组</li>
* <li>使用默认参数的构造方法</li>
* </ul>
* <p>
* 对于接口或抽象类型构造其默认实现
* <pre>
* Map - HashMap
* Collction - ArrayList
* List - ArrayList
* Set - HashSet
* </pre>
*
* @param <T> 对象类型
*/
public class PossibleObjectCreator<T> implements ObjectCreator<T> {
/**
* 创建默认的对象实例化器
*
* @param clazz 实例化的类
* @param <T> 对象类型
* @return DefaultObjectCreator
*/
public static <T> PossibleObjectCreator<T> of(final Class<T> clazz) {
return new PossibleObjectCreator<>(clazz);
}
final Class<T> clazz;
/**
* 构造
*
* @param clazz 实例化的类
*/
public PossibleObjectCreator(final Class<T> clazz) {
this.clazz = Assert.notNull(clazz);
}
@Override
@SuppressWarnings("unchecked")
public T create() {
Class<T> type = this.clazz;
// 原始类型
if (type.isPrimitive()) {
return (T) ClassUtil.getPrimitiveDefaultValue(type);
}
// 某些特殊接口的实例化按照默认实现进行
if (type.isAssignableFrom(AbstractMap.class)) {
type = (Class<T>) HashMap.class;
} else if (type.isAssignableFrom(List.class)) {
type = (Class<T>) ArrayList.class;
} else if (type.isAssignableFrom(Set.class)) {
type = (Class<T>) 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<T>[] constructors = ConstructorUtil.getConstructors(type);
Class<?>[] parameterTypes;
for (final Constructor<T> 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;
}
}

View File

@ -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;