mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-05-09 23:51:34 +08:00
fix code
This commit is contained in:
parent
241aea60e4
commit
2c3eac6046
@ -0,0 +1,366 @@
|
||||
/*
|
||||
* 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:
|
||||
* http://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.classloader;
|
||||
|
||||
import org.dromara.hutool.core.exceptions.UtilException;
|
||||
import org.dromara.hutool.core.lang.Assert;
|
||||
import org.dromara.hutool.core.map.BiMap;
|
||||
import org.dromara.hutool.core.reflect.ClassUtil;
|
||||
import org.dromara.hutool.core.text.StrTrimer;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.util.CharUtil;
|
||||
|
||||
import java.lang.reflect.Executable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.security.CodeSource;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* 类描述工具类<br>
|
||||
* 来自:org.apache.dubbo.common.utils.ReflectUtils
|
||||
*
|
||||
* @author Dubbo
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class ClassDescUtil {
|
||||
/**
|
||||
* void(V).
|
||||
*/
|
||||
public static final char JVM_VOID = 'V';
|
||||
|
||||
/**
|
||||
* boolean(Z).
|
||||
*/
|
||||
public static final char JVM_BOOLEAN = 'Z';
|
||||
|
||||
/**
|
||||
* byte(B).
|
||||
*/
|
||||
public static final char JVM_BYTE = 'B';
|
||||
|
||||
/**
|
||||
* char(C).
|
||||
*/
|
||||
public static final char JVM_CHAR = 'C';
|
||||
|
||||
/**
|
||||
* double(D).
|
||||
*/
|
||||
public static final char JVM_DOUBLE = 'D';
|
||||
|
||||
/**
|
||||
* float(F).
|
||||
*/
|
||||
public static final char JVM_FLOAT = 'F';
|
||||
|
||||
/**
|
||||
* int(I).
|
||||
*/
|
||||
public static final char JVM_INT = 'I';
|
||||
|
||||
/**
|
||||
* long(J).
|
||||
*/
|
||||
public static final char JVM_LONG = 'J';
|
||||
|
||||
/**
|
||||
* short(S).
|
||||
*/
|
||||
public static final char JVM_SHORT = 'S';
|
||||
|
||||
/**
|
||||
* 原始类型名和其class对应表,例如:int.class 《=》 int
|
||||
*/
|
||||
private static final BiMap<Class<?>, Character> PRIMITIVE_CLASS_DESC_MAP = new BiMap<>(new HashMap<>(9, 1));
|
||||
private static final BiMap<Class<?>, String> PRIMITIVE_CLASS_NAME_MAP = new BiMap<>(new HashMap<>(9, 1));
|
||||
|
||||
static {
|
||||
PRIMITIVE_CLASS_DESC_MAP.put(void.class, JVM_VOID);
|
||||
PRIMITIVE_CLASS_NAME_MAP.put(void.class, "void");
|
||||
PRIMITIVE_CLASS_DESC_MAP.put(boolean.class, JVM_BOOLEAN);
|
||||
PRIMITIVE_CLASS_NAME_MAP.put(boolean.class, "boolean");
|
||||
PRIMITIVE_CLASS_DESC_MAP.put(byte.class, JVM_BYTE);
|
||||
PRIMITIVE_CLASS_NAME_MAP.put(byte.class, "byte");
|
||||
PRIMITIVE_CLASS_DESC_MAP.put(char.class, JVM_CHAR);
|
||||
PRIMITIVE_CLASS_NAME_MAP.put(char.class, "char");
|
||||
PRIMITIVE_CLASS_DESC_MAP.put(double.class, JVM_DOUBLE);
|
||||
PRIMITIVE_CLASS_NAME_MAP.put(double.class, "double");
|
||||
PRIMITIVE_CLASS_DESC_MAP.put(float.class, JVM_FLOAT);
|
||||
PRIMITIVE_CLASS_NAME_MAP.put(float.class, "float");
|
||||
PRIMITIVE_CLASS_DESC_MAP.put(int.class, JVM_INT);
|
||||
PRIMITIVE_CLASS_NAME_MAP.put(int.class, "int");
|
||||
PRIMITIVE_CLASS_DESC_MAP.put(long.class, JVM_LONG);
|
||||
PRIMITIVE_CLASS_NAME_MAP.put(long.class, "long");
|
||||
PRIMITIVE_CLASS_DESC_MAP.put(short.class, JVM_SHORT);
|
||||
PRIMITIVE_CLASS_NAME_MAP.put(short.class, "short");
|
||||
}
|
||||
|
||||
/**
|
||||
* Class描述转Class
|
||||
* <pre>{@code
|
||||
* "[Z" => boolean[].class
|
||||
* "[[Ljava/util/Map;" => java.util.Map[][].class
|
||||
* }</pre>
|
||||
*
|
||||
* @param desc 类描述
|
||||
* @return Class
|
||||
* @throws UtilException 类没有找到
|
||||
*/
|
||||
public static Class<?> descToClass(final String desc) throws UtilException {
|
||||
return descToClass(desc, true, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class描述转Class
|
||||
* <pre>{@code
|
||||
* "[Z" => boolean[].class
|
||||
* "[[Ljava/util/Map;" => java.util.Map[][].class
|
||||
* }</pre>
|
||||
*
|
||||
* @param desc 类描述
|
||||
* @param isInitialized 是否初始化类
|
||||
* @param cl {@link ClassLoader}
|
||||
* @return Class
|
||||
* @throws UtilException 类没有找到
|
||||
*/
|
||||
public static Class<?> descToClass(String desc, final boolean isInitialized, final ClassLoader cl) throws UtilException {
|
||||
final char firstChar = desc.charAt(0);
|
||||
final Class<?> clazz = PRIMITIVE_CLASS_DESC_MAP.getKey(firstChar);
|
||||
if (null != clazz) {
|
||||
return clazz;
|
||||
}
|
||||
switch (firstChar) {
|
||||
case 'L':
|
||||
// "Ljava/lang/Object;" ==> "java.lang.Object"
|
||||
desc = desc.substring(1, desc.length() - 1).replace('/', '.');
|
||||
break;
|
||||
case '[':
|
||||
// "[[Ljava/lang/Object;" ==> "[[Ljava.lang.Object;"
|
||||
desc = desc.replace(CharUtil.SLASH, CharUtil.DOT);
|
||||
break;
|
||||
default:
|
||||
throw new UtilException("Class not found for : " + desc);
|
||||
}
|
||||
|
||||
return ClassUtil.forName(desc, isInitialized, cl);
|
||||
}
|
||||
|
||||
/**
|
||||
* get class desc.
|
||||
* boolean[].class => "[Z"
|
||||
* Object.class => "Ljava/lang/Object;"
|
||||
*
|
||||
* @param c class.
|
||||
* @return desc.
|
||||
*/
|
||||
public static String getDesc(Class<?> c) {
|
||||
final StringBuilder ret = new StringBuilder();
|
||||
|
||||
while (c.isArray()) {
|
||||
ret.append('[');
|
||||
c = c.getComponentType();
|
||||
}
|
||||
|
||||
if (c.isPrimitive()) {
|
||||
final Character desc = PRIMITIVE_CLASS_DESC_MAP.get(c);
|
||||
if (null != desc) {
|
||||
ret.append(desc.charValue());
|
||||
}
|
||||
} else {
|
||||
ret.append('L');
|
||||
ret.append(c.getName().replace('.', '/'));
|
||||
ret.append(';');
|
||||
}
|
||||
return ret.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取方法或构造描述<br>
|
||||
* 方法:
|
||||
* <pre>{@code
|
||||
* int do(int arg1) => "do(I)I"
|
||||
* void do(String arg1,boolean arg2) => "do(Ljava/lang/String;Z)V"
|
||||
* }</pre>
|
||||
* 构造:
|
||||
* <pre>
|
||||
* "()V", "(Ljava/lang/String;I)V"
|
||||
* </pre>
|
||||
*
|
||||
* @param methodOrConstructor 方法或构造
|
||||
* @return 描述
|
||||
*/
|
||||
public static String getDesc(final Executable methodOrConstructor) {
|
||||
final StringBuilder ret = new StringBuilder();
|
||||
if (methodOrConstructor instanceof Method) {
|
||||
ret.append(methodOrConstructor.getName());
|
||||
}
|
||||
ret.append('(');
|
||||
|
||||
// 参数
|
||||
final Class<?>[] parameterTypes = methodOrConstructor.getParameterTypes();
|
||||
for (final Class<?> parameterType : parameterTypes) {
|
||||
ret.append(getDesc(parameterType));
|
||||
}
|
||||
|
||||
// 返回类型或构造标记
|
||||
ret.append(')');
|
||||
if (methodOrConstructor instanceof Method) {
|
||||
ret.append(getDesc(((Method) methodOrConstructor).getReturnType()));
|
||||
} else {
|
||||
ret.append('V');
|
||||
}
|
||||
|
||||
return ret.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取code base
|
||||
*
|
||||
* @param clazz 类
|
||||
* @return code base
|
||||
*/
|
||||
public static String getCodeBase(final Class<?> clazz) {
|
||||
if (clazz == null) {
|
||||
return null;
|
||||
}
|
||||
final ProtectionDomain domain = clazz.getProtectionDomain();
|
||||
if (domain == null) {
|
||||
return null;
|
||||
}
|
||||
final CodeSource source = domain.getCodeSource();
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
final URL location = source.getLocation();
|
||||
if (location == null) {
|
||||
return null;
|
||||
}
|
||||
return location.getFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* name to class.
|
||||
* "boolean" => boolean.class
|
||||
* "java.util.Map[][]" => java.util.Map[][].class
|
||||
*
|
||||
* @param name name.
|
||||
* @param isInitialized 是否初始化类
|
||||
* @param cl ClassLoader instance.
|
||||
* @return Class instance.
|
||||
*/
|
||||
public static Class<?> nameToClass(String name, final boolean isInitialized, final ClassLoader cl) {
|
||||
Assert.notNull(name, "Name must not be null");
|
||||
// 去除尾部多余的"."和"/"
|
||||
name = StrUtil.trim(name, StrTrimer.TrimMode.SUFFIX, (c) ->
|
||||
CharUtil.SLASH == c || CharUtil.DOT == c);
|
||||
|
||||
int c = 0;
|
||||
final int index = name.indexOf('[');
|
||||
if (index > 0) {
|
||||
c = (name.length() - index) / 2;
|
||||
name = name.substring(0, index);
|
||||
}
|
||||
|
||||
if (c > 0) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
while (c-- > 0) {
|
||||
sb.append('[');
|
||||
}
|
||||
|
||||
final Class<?> clazz = PRIMITIVE_CLASS_NAME_MAP.getKey(name);
|
||||
if (null != clazz) {
|
||||
// 原始类型数组,根据name获取其描述
|
||||
sb.append(PRIMITIVE_CLASS_DESC_MAP.get(clazz).charValue());
|
||||
} else {
|
||||
// 对象数组
|
||||
// "java.lang.Object" ==> "Ljava.lang.Object;"
|
||||
sb.append('L').append(name).append(';');
|
||||
}
|
||||
name = sb.toString();
|
||||
} else {
|
||||
final Class<?> clazz = PRIMITIVE_CLASS_NAME_MAP.getKey(name);
|
||||
if (null != clazz) {
|
||||
return clazz;
|
||||
}
|
||||
}
|
||||
|
||||
return ClassUtil.forName(name.replace(CharUtil.SLASH, CharUtil.DOT), isInitialized, cl);
|
||||
}
|
||||
|
||||
/**
|
||||
* 类名称转描述
|
||||
*
|
||||
* <pre>{@code
|
||||
* java.util.Map[][] => "[[Ljava/util/Map;"
|
||||
* }</pre>
|
||||
*
|
||||
* @param name 名称
|
||||
* @return 描述
|
||||
*/
|
||||
public static String nameToDesc(String name) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
int c = 0;
|
||||
final int index = name.indexOf('[');
|
||||
if (index > 0) {
|
||||
c = (name.length() - index) / 2;
|
||||
name = name.substring(0, index);
|
||||
}
|
||||
while (c-- > 0) {
|
||||
sb.append('[');
|
||||
}
|
||||
|
||||
final Class<?> clazz = PRIMITIVE_CLASS_NAME_MAP.getKey(name);
|
||||
if (null != clazz) {
|
||||
// 原始类型数组,根据name获取其描述
|
||||
sb.append(PRIMITIVE_CLASS_DESC_MAP.get(clazz).charValue());
|
||||
} else {
|
||||
// 对象数组
|
||||
// "java.lang.Object" ==> "Ljava.lang.Object;"
|
||||
sb.append('L').append(name.replace(CharUtil.DOT, CharUtil.SLASH)).append(';');
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 类描述转名称
|
||||
*
|
||||
* <pre>{@code
|
||||
* "[[I" => "int[][]"
|
||||
* }</pre>
|
||||
*
|
||||
* @param desc 描述
|
||||
* @return 名称
|
||||
*/
|
||||
public static String descToName(final String desc) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
int c = desc.lastIndexOf('[') + 1;
|
||||
if (desc.length() == c + 1) {
|
||||
final char descChar = desc.charAt(c);
|
||||
final Class<?> clazz = PRIMITIVE_CLASS_DESC_MAP.getKey(descChar);
|
||||
if (null != clazz) {
|
||||
sb.append(PRIMITIVE_CLASS_NAME_MAP.get(clazz));
|
||||
} else {
|
||||
throw new UtilException("Unsupported primitive desc: {}", desc);
|
||||
}
|
||||
} else {
|
||||
sb.append(desc.substring(c + 1, desc.length() - 1).replace(CharUtil.SLASH, CharUtil.DOT));
|
||||
}
|
||||
while (c-- > 0) {
|
||||
sb.append("[]");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
@ -12,22 +12,11 @@
|
||||
|
||||
package org.dromara.hutool.core.classloader;
|
||||
|
||||
import org.dromara.hutool.core.convert.BasicType;
|
||||
import org.dromara.hutool.core.exceptions.UtilException;
|
||||
import org.dromara.hutool.core.lang.Assert;
|
||||
import org.dromara.hutool.core.map.SafeConcurrentHashMap;
|
||||
import org.dromara.hutool.core.text.CharPool;
|
||||
import org.dromara.hutool.core.text.StrTrimer;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.util.CharUtil;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Array;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* {@link ClassLoader}工具类<br>
|
||||
@ -39,48 +28,26 @@ import java.util.Map;
|
||||
public class ClassLoaderUtil {
|
||||
|
||||
/**
|
||||
* 数组类的结尾符: "[]"
|
||||
* 获取{@link ClassLoader}<br>
|
||||
* 获取顺序如下:<br>
|
||||
*
|
||||
* <pre>
|
||||
* 1、获取当前线程的ContextClassLoader
|
||||
* 2、获取当前类对应的ClassLoader
|
||||
* 3、获取系统ClassLoader({@link ClassLoader#getSystemClassLoader()})
|
||||
* </pre>
|
||||
*
|
||||
* @return 类加载器
|
||||
*/
|
||||
private static final String ARRAY_SUFFIX = "[]";
|
||||
/**
|
||||
* 内部数组类名前缀: "["
|
||||
*/
|
||||
private static final String INTERNAL_ARRAY_PREFIX = "[";
|
||||
/**
|
||||
* 内部非原始类型类名前缀: "[L"
|
||||
*/
|
||||
private static final String NON_PRIMITIVE_ARRAY_PREFIX = "[L";
|
||||
/**
|
||||
* 包名分界符: '.'
|
||||
*/
|
||||
private static final char PACKAGE_SEPARATOR = CharUtil.DOT;
|
||||
/**
|
||||
* 内部类分界符: '$'
|
||||
*/
|
||||
private static final char INNER_CLASS_SEPARATOR = '$';
|
||||
|
||||
/**
|
||||
* 原始类型名和其class对应表,例如:int =》 int.class
|
||||
*/
|
||||
private static final Map<String, Class<?>> PRIMITIVE_TYPE_NAME_MAP = new SafeConcurrentHashMap<>(32);
|
||||
|
||||
static {
|
||||
final List<Class<?>> primitiveTypes = new ArrayList<>(32);
|
||||
// 加入原始类型
|
||||
primitiveTypes.addAll(BasicType.getPrimitiveSet());
|
||||
// 加入原始类型数组类型
|
||||
primitiveTypes.add(boolean[].class);
|
||||
primitiveTypes.add(byte[].class);
|
||||
primitiveTypes.add(char[].class);
|
||||
primitiveTypes.add(double[].class);
|
||||
primitiveTypes.add(float[].class);
|
||||
primitiveTypes.add(int[].class);
|
||||
primitiveTypes.add(long[].class);
|
||||
primitiveTypes.add(short[].class);
|
||||
primitiveTypes.add(void.class);
|
||||
for (final Class<?> primitiveType : primitiveTypes) {
|
||||
PRIMITIVE_TYPE_NAME_MAP.put(primitiveType.getName(), primitiveType);
|
||||
public static ClassLoader getClassLoader() {
|
||||
ClassLoader classLoader = getContextClassLoader();
|
||||
if (classLoader == null) {
|
||||
classLoader = ClassLoaderUtil.class.getClassLoader();
|
||||
if (null == classLoader) {
|
||||
classLoader = getSystemClassLoader();
|
||||
}
|
||||
}
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -116,32 +83,17 @@ public class ClassLoaderUtil {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取{@link ClassLoader}<br>
|
||||
* 获取顺序如下:<br>
|
||||
* 创建新的{@link JarClassLoader},并使用此Classloader加载目录下的class文件和jar文件
|
||||
*
|
||||
* <pre>
|
||||
* 1、获取当前线程的ContextClassLoader
|
||||
* 2、获取当前类对应的ClassLoader
|
||||
* 3、获取系统ClassLoader({@link ClassLoader#getSystemClassLoader()})
|
||||
* </pre>
|
||||
*
|
||||
* @return 类加载器
|
||||
* @param jarOrDir jar文件或者包含jar和class文件的目录
|
||||
* @return {@link JarClassLoader}
|
||||
* @since 4.4.2
|
||||
*/
|
||||
public static ClassLoader getClassLoader() {
|
||||
ClassLoader classLoader = getContextClassLoader();
|
||||
if (classLoader == null) {
|
||||
classLoader = ClassLoaderUtil.class.getClassLoader();
|
||||
if (null == classLoader) {
|
||||
classLoader = getSystemClassLoader();
|
||||
}
|
||||
}
|
||||
return classLoader;
|
||||
public static JarClassLoader getJarClassLoader(final File jarOrDir) {
|
||||
return JarClassLoader.load(jarOrDir);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------- loadClass
|
||||
|
||||
/**
|
||||
* 加载类,通过传入类的字符串,返回其对应的类名,使用默认ClassLoader并初始化类(调用static模块内容和初始化static属性)<br>
|
||||
* 扩展{@link Class#forName(String, boolean, ClassLoader)}方法,支持以下几类类名的加载:
|
||||
@ -201,48 +153,8 @@ public class ClassLoaderUtil {
|
||||
* @throws UtilException 包装{@link ClassNotFoundException},没有类名对应的类时抛出此异常
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> Class<T> loadClass(String name, final boolean isInitialized, ClassLoader classLoader) throws UtilException {
|
||||
Assert.notNull(name, "Name must not be null");
|
||||
|
||||
// 自动将包名中的"/"替换为"."
|
||||
name = name.replace(CharPool.SLASH, CharPool.DOT);
|
||||
if (null == classLoader) {
|
||||
classLoader = getClassLoader();
|
||||
}
|
||||
|
||||
Class<?> clazz = loadPrimitiveClass(name);
|
||||
if (clazz == null) {
|
||||
clazz = doLoadClass(name, isInitialized, classLoader);
|
||||
}
|
||||
return (Class<T>) clazz;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载原始类型的类。包括原始类型、原始类型数组和void
|
||||
*
|
||||
* @param name 原始类型名,比如 int
|
||||
* @return 原始类型类
|
||||
*/
|
||||
public static Class<?> loadPrimitiveClass(String name) {
|
||||
Class<?> result = null;
|
||||
if (StrUtil.isNotBlank(name)) {
|
||||
name = name.trim();
|
||||
if (name.length() <= 8) {
|
||||
result = PRIMITIVE_TYPE_NAME_MAP.get(name);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建新的{@link JarClassLoader},并使用此Classloader加载目录下的class文件和jar文件
|
||||
*
|
||||
* @param jarOrDir jar文件或者包含jar和class文件的目录
|
||||
* @return {@link JarClassLoader}
|
||||
* @since 4.4.2
|
||||
*/
|
||||
public static JarClassLoader getJarClassLoader(final File jarOrDir) {
|
||||
return JarClassLoader.load(jarOrDir);
|
||||
public static <T> Class<T> loadClass(final String name, final boolean isInitialized, final ClassLoader classLoader) throws UtilException {
|
||||
return (Class<T>) ClassDescUtil.nameToClass(name, isInitialized, classLoader);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -292,95 +204,4 @@ public class ClassLoaderUtil {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------------- Private method start
|
||||
|
||||
/**
|
||||
* 加载非原始类类,无缓存
|
||||
*
|
||||
* @param name 类名
|
||||
* @param isInitialized 是否初始化
|
||||
* @param classLoader {@link ClassLoader},必须非空
|
||||
* @return 类
|
||||
*/
|
||||
private static Class<?> doLoadClass(String name, final boolean isInitialized, final ClassLoader classLoader) {
|
||||
// 去除尾部多余的"."
|
||||
name = StrUtil.trim(name, StrTrimer.TrimMode.SUFFIX, (c) -> CharUtil.DOT == c);
|
||||
Class<?> clazz;
|
||||
if (name.endsWith(ARRAY_SUFFIX)) {
|
||||
// 对象数组"java.lang.String[]"风格
|
||||
final String elementClassName = name.substring(0, name.length() - ARRAY_SUFFIX.length());
|
||||
final Class<?> elementClass = loadClass(elementClassName, isInitialized, classLoader);
|
||||
clazz = Array.newInstance(elementClass, 0).getClass();
|
||||
} else if (name.startsWith(NON_PRIMITIVE_ARRAY_PREFIX) && name.endsWith(";")) {
|
||||
// "[Ljava.lang.String;" 风格
|
||||
final String elementName = name.substring(NON_PRIMITIVE_ARRAY_PREFIX.length(), name.length() - 1);
|
||||
final Class<?> elementClass = loadClass(elementName, isInitialized, classLoader);
|
||||
clazz = Array.newInstance(elementClass, 0).getClass();
|
||||
} else if (name.startsWith(INTERNAL_ARRAY_PREFIX)) {
|
||||
// "[[I" 或 "[[Ljava.lang.String;" 风格
|
||||
final String elementName = name.substring(INTERNAL_ARRAY_PREFIX.length());
|
||||
final Class<?> elementClass = loadClass(elementName, isInitialized, classLoader);
|
||||
clazz = Array.newInstance(elementClass, 0).getClass();
|
||||
} else {
|
||||
// 加载普通类
|
||||
try {
|
||||
clazz = Class.forName(name, isInitialized, classLoader);
|
||||
} catch (final ClassNotFoundException ex) {
|
||||
// 尝试获取内部类,例如java.lang.Thread.State =》java.lang.Thread$State
|
||||
clazz = tryLoadInnerClass(name, classLoader, isInitialized);
|
||||
if (null == clazz) {
|
||||
throw new UtilException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
return clazz;
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试转换并加载内部类,例如java.lang.Thread.State =》java.lang.Thread$State
|
||||
*
|
||||
* @param name 类名
|
||||
* @param classLoader {@link ClassLoader},{@code null} 则使用系统默认ClassLoader
|
||||
* @param isInitialized 是否初始化类(调用static模块内容和初始化static属性)
|
||||
* @return 类名对应的类
|
||||
* @since 4.1.20
|
||||
*/
|
||||
private static Class<?> tryLoadInnerClass(String name, final ClassLoader classLoader, final boolean isInitialized) {
|
||||
// 尝试获取内部类,例如java.lang.Thread.State =》java.lang.Thread$State
|
||||
int lastDotIndex = name.lastIndexOf(PACKAGE_SEPARATOR);
|
||||
Class<?> clazz = null;
|
||||
while (lastDotIndex > 0) {// 类与内部类的分隔符不能在第一位,因此>0
|
||||
if (!Character.isUpperCase(name.charAt(lastDotIndex + 1))) {
|
||||
// 类名必须大写,非大写的类名跳过
|
||||
break;
|
||||
}
|
||||
name = name.substring(0, lastDotIndex) + INNER_CLASS_SEPARATOR + name.substring(lastDotIndex + 1);
|
||||
clazz = forName(name, isInitialized, classLoader);
|
||||
if (null != clazz) {
|
||||
break;
|
||||
}
|
||||
|
||||
lastDotIndex = name.lastIndexOf(PACKAGE_SEPARATOR);
|
||||
}
|
||||
return clazz;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载指定名称的类
|
||||
*
|
||||
* @param name 类名
|
||||
* @param initialize 是否初始化
|
||||
* @param loader {@link ClassLoader}
|
||||
* @return 指定名称对应的类,如果不存在类,返回{@code null}
|
||||
*/
|
||||
private static Class<?> forName(final String name, final boolean initialize, final ClassLoader loader) {
|
||||
try {
|
||||
return Class.forName(name, initialize, loader);
|
||||
} catch (final ClassNotFoundException ex2) {
|
||||
// 尝试获取内部类失败时,忽略之。
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// ----------------------------------------------------------------------------------- Private method end
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import org.dromara.hutool.core.collection.iter.EnumerationIter;
|
||||
import org.dromara.hutool.core.collection.iter.IterUtil;
|
||||
import org.dromara.hutool.core.io.file.FileUtil;
|
||||
import org.dromara.hutool.core.io.IORuntimeException;
|
||||
import org.dromara.hutool.core.lang.Assert;
|
||||
import org.dromara.hutool.core.util.CharsetUtil;
|
||||
import org.dromara.hutool.core.classloader.ClassLoaderUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
@ -30,6 +31,7 @@ import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
/**
|
||||
@ -290,4 +292,49 @@ public class ResourceUtil {
|
||||
}
|
||||
return resources;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载配置文件内容到{@link Properties}中<br>
|
||||
* 需要注意的是,如果资源文件的扩展名是.xml,会调用{@link Properties#loadFromXML(InputStream)} 读取。
|
||||
*
|
||||
* @param properties {@link Properties}文件
|
||||
* @param resource 资源
|
||||
* @param charset 编码,对XML无效
|
||||
*/
|
||||
public static void loadTo(final Properties properties, final Resource resource, final Charset charset) {
|
||||
Assert.notNull(properties);
|
||||
Assert.notNull(resource);
|
||||
final String filename = resource.getName();
|
||||
if (filename != null && StrUtil.endWithIgnoreCase(filename, ".xml")) {
|
||||
// XML
|
||||
try (final InputStream in = resource.getStream()) {
|
||||
properties.loadFromXML(in);
|
||||
} catch (final IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
// .properties
|
||||
try (final BufferedReader reader = resource.getReader(
|
||||
ObjUtil.defaultIfNull(charset, CharsetUtil.UTF_8))) {
|
||||
properties.load(reader);
|
||||
} catch (final IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载指定名称的所有配置文件内容到{@link Properties}中
|
||||
*
|
||||
* @param properties {@link Properties}文件
|
||||
* @param resourceName 资源名,可以是相对classpath的路径,也可以是绝对路径
|
||||
* @param classLoader {@link ClassLoader},{@code null}表示使用默认的当前上下文ClassLoader
|
||||
* @param charset 编码,对XML无效
|
||||
*/
|
||||
public static void loadAllTo(final Properties properties, final String resourceName,
|
||||
final ClassLoader classLoader, final Charset charset) {
|
||||
for (final Resource resource : getResources(resourceName, classLoader)) {
|
||||
loadTo(properties, resource, charset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,6 +49,15 @@ import java.util.function.Predicate;
|
||||
*/
|
||||
public class ClassUtil {
|
||||
|
||||
/**
|
||||
* 包名分界符: '.'
|
||||
*/
|
||||
private static final char PACKAGE_SEPARATOR = CharUtil.DOT;
|
||||
/**
|
||||
* 内部类分界符: '$'
|
||||
*/
|
||||
private static final char INNER_CLASS_SEPARATOR = '$';
|
||||
|
||||
/**
|
||||
* {@code null}安全的获取对象类型
|
||||
*
|
||||
@ -726,6 +735,64 @@ public class ClassUtil {
|
||||
return new ArrayList<>(interfacesFound);
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载指定名称的类
|
||||
*
|
||||
* @param name 类名
|
||||
* @param isInitialized 是否初始化
|
||||
* @param loader {@link ClassLoader},{@code null}表示默认
|
||||
* @return 指定名称对应的类,如果不存在类,返回{@code null
|
||||
* @link Class#forName(String, boolean, ClassLoader)}
|
||||
*/
|
||||
public static Class<?> forName(final String name, final boolean isInitialized, ClassLoader loader) {
|
||||
if(null == loader){
|
||||
loader = ClassLoaderUtil.getClassLoader();
|
||||
}
|
||||
|
||||
// 加载普通类
|
||||
try {
|
||||
return Class.forName(name, isInitialized, loader);
|
||||
} catch (final ClassNotFoundException ex) {
|
||||
// 尝试获取内部类,例如java.lang.Thread.State =》java.lang.Thread$State
|
||||
final Class<?> clazz = forNameInnerClass(name, isInitialized, loader);
|
||||
if (null == clazz) {
|
||||
throw new UtilException(ex);
|
||||
}
|
||||
return clazz;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试转换并加载内部类,例如java.lang.Thread.State =》java.lang.Thread$State
|
||||
*
|
||||
* @param name 类名
|
||||
* @param classLoader {@link ClassLoader},{@code null} 则使用系统默认ClassLoader
|
||||
* @param isInitialized 是否初始化类(调用static模块内容和初始化static属性)
|
||||
* @return 类名对应的类,未找到返回{@code null}
|
||||
*/
|
||||
private static Class<?> forNameInnerClass(String name, final boolean isInitialized, final ClassLoader classLoader) {
|
||||
// 尝试获取内部类,例如java.lang.Thread.State =》java.lang.Thread$State
|
||||
int lastDotIndex = name.lastIndexOf(PACKAGE_SEPARATOR);
|
||||
Class<?> clazz = null;
|
||||
while (lastDotIndex > 0) {// 类与内部类的分隔符不能在第一位,因此>0
|
||||
if (!Character.isUpperCase(name.charAt(lastDotIndex + 1))) {
|
||||
// 类名必须大写,非大写的类名跳过
|
||||
break;
|
||||
}
|
||||
name = name.substring(0, lastDotIndex) + INNER_CLASS_SEPARATOR + name.substring(lastDotIndex + 1);
|
||||
try {
|
||||
clazz = Class.forName(name, isInitialized, classLoader);
|
||||
break;
|
||||
} catch (final ClassNotFoundException ignore) {
|
||||
//ignore
|
||||
}
|
||||
|
||||
// 继续向前替换.为$
|
||||
lastDotIndex = name.lastIndexOf(PACKAGE_SEPARATOR);
|
||||
}
|
||||
return clazz;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定类的的接口列表
|
||||
*
|
||||
|
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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:
|
||||
* http://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.spi;
|
||||
|
||||
import org.dromara.hutool.core.classloader.ClassLoaderUtil;
|
||||
import org.dromara.hutool.core.io.resource.ResourceUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Properties;
|
||||
|
||||
public class KVServiceLoader<S> implements ServiceLoader<S>{
|
||||
|
||||
private final String pathPrefix;
|
||||
private final Class<S> serviceClass;
|
||||
private final ClassLoader classLoader;
|
||||
private final Charset charset;
|
||||
|
||||
private Properties serviceProperties;
|
||||
|
||||
public KVServiceLoader(final String pathPrefix, final Class<S> serviceClass,
|
||||
final ClassLoader classLoader, final Charset charset) {
|
||||
this.pathPrefix = pathPrefix;
|
||||
this.serviceClass = serviceClass;
|
||||
this.classLoader = classLoader;
|
||||
this.charset = charset;
|
||||
|
||||
load();
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载或重新加载全部服务
|
||||
* @return this
|
||||
*/
|
||||
public KVServiceLoader<S> load(){
|
||||
final Properties properties = new Properties();
|
||||
ResourceUtil.loadAllTo(
|
||||
properties,
|
||||
pathPrefix + serviceClass.getName(),
|
||||
classLoader,
|
||||
charset);
|
||||
this.serviceProperties = properties;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Class<S> getServiceClass(final String serviceName){
|
||||
final String serviceClassName = this.serviceProperties.getProperty(serviceName);
|
||||
if(StrUtil.isNotBlank(serviceClassName)){
|
||||
return ClassLoaderUtil.loadClass(serviceClassName);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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:
|
||||
* http://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.spi;
|
||||
|
||||
/**
|
||||
* SPI服务加载接口<br>
|
||||
* 用户实现此接口用于制定不同的服务加载方式
|
||||
*
|
||||
* @param <T> 服务对象类型
|
||||
* @author looly
|
||||
*/
|
||||
public interface ServiceLoader<T> {
|
||||
}
|
@ -10,10 +10,11 @@
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.core.util;
|
||||
package org.dromara.hutool.core.spi;
|
||||
|
||||
import org.dromara.hutool.core.classloader.ClassLoaderUtil;
|
||||
import org.dromara.hutool.core.collection.ListUtil;
|
||||
import org.dromara.hutool.core.util.ObjUtil;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* 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:
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 服务提供接口SPI(Service Provider interface)机制相关封装
|
||||
*/
|
||||
package org.dromara.hutool.core.spi;
|
@ -608,7 +608,8 @@ public class BeanUtilTest {
|
||||
o.setAge(123);
|
||||
o.setOpenid("asd");
|
||||
|
||||
@SuppressWarnings("unchecked") final CopyOptions copyOptions = CopyOptions.of().setIgnoreProperties(Person::getAge,Person::getOpenid);
|
||||
@SuppressWarnings("unchecked")
|
||||
final CopyOptions copyOptions = CopyOptions.of().setIgnoreProperties(Person::getAge,Person::getOpenid);
|
||||
final Person n = new Person();
|
||||
BeanUtil.copyProperties(o, n, copyOptions);
|
||||
|
||||
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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:
|
||||
* http://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.classloader;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
/**
|
||||
* 来自:org.apache.dubbo.common.utils.ReflectUtilsTest
|
||||
*/
|
||||
public class ClassDescTest {
|
||||
|
||||
@Test
|
||||
void testDesc2Class() {
|
||||
assertEquals(void.class, ClassDescUtil.descToClass("V"));
|
||||
assertEquals(boolean.class, ClassDescUtil.descToClass("Z"));
|
||||
assertEquals(boolean[].class, ClassDescUtil.descToClass("[Z"));
|
||||
assertEquals(byte.class, ClassDescUtil.descToClass("B"));
|
||||
assertEquals(char.class, ClassDescUtil.descToClass("C"));
|
||||
assertEquals(double.class, ClassDescUtil.descToClass("D"));
|
||||
assertEquals(float.class, ClassDescUtil.descToClass("F"));
|
||||
assertEquals(int.class, ClassDescUtil.descToClass("I"));
|
||||
assertEquals(long.class, ClassDescUtil.descToClass("J"));
|
||||
assertEquals(short.class, ClassDescUtil.descToClass("S"));
|
||||
assertEquals(String.class, ClassDescUtil.descToClass("Ljava.lang.String;"));
|
||||
assertEquals(int[][].class, ClassDescUtil.descToClass(ClassDescUtil.getDesc(int[][].class)));
|
||||
assertEquals(ClassDescTest[].class, ClassDescUtil.descToClass(ClassDescUtil.getDesc(ClassDescTest[].class)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void getDescTest() {
|
||||
// getDesc
|
||||
assertEquals("Z", ClassDescUtil.getDesc(boolean.class));
|
||||
assertEquals("[[[I", ClassDescUtil.getDesc(int[][][].class));
|
||||
assertEquals("[[Ljava/lang/Object;", ClassDescUtil.getDesc(Object[][].class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void nameToClassTest() {
|
||||
final Class<?> aClass = ClassDescUtil.nameToClass("java.lang.Object[]", true, null);
|
||||
assertEquals(Object[].class, aClass);
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@
|
||||
|
||||
package org.dromara.hutool.crypto.provider;
|
||||
|
||||
import org.dromara.hutool.core.util.ServiceLoaderUtil;
|
||||
import org.dromara.hutool.core.spi.ServiceLoaderUtil;
|
||||
import org.dromara.hutool.crypto.SecureUtil;
|
||||
|
||||
import java.security.Provider;
|
||||
|
@ -13,7 +13,7 @@
|
||||
package org.dromara.hutool.extra.aop.proxy;
|
||||
|
||||
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
||||
import org.dromara.hutool.core.util.ServiceLoaderUtil;
|
||||
import org.dromara.hutool.core.spi.ServiceLoaderUtil;
|
||||
import org.dromara.hutool.extra.aop.aspects.Aspect;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
@ -13,7 +13,7 @@
|
||||
package org.dromara.hutool.extra.expression.engine;
|
||||
|
||||
import org.dromara.hutool.core.lang.Singleton;
|
||||
import org.dromara.hutool.core.util.ServiceLoaderUtil;
|
||||
import org.dromara.hutool.core.spi.ServiceLoaderUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.log.StaticLog;
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
package org.dromara.hutool.extra.pinyin.engine;
|
||||
|
||||
import org.dromara.hutool.core.lang.Singleton;
|
||||
import org.dromara.hutool.core.util.ServiceLoaderUtil;
|
||||
import org.dromara.hutool.core.spi.ServiceLoaderUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.log.StaticLog;
|
||||
|
||||
|
@ -15,7 +15,7 @@ package org.dromara.hutool.extra.template.engine;
|
||||
import org.dromara.hutool.core.lang.Singleton;
|
||||
import org.dromara.hutool.core.reflect.ConstructorUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.util.ServiceLoaderUtil;
|
||||
import org.dromara.hutool.core.spi.ServiceLoaderUtil;
|
||||
import org.dromara.hutool.extra.template.TemplateConfig;
|
||||
import org.dromara.hutool.extra.template.TemplateEngine;
|
||||
import org.dromara.hutool.extra.template.TemplateException;
|
||||
|
@ -13,7 +13,7 @@
|
||||
package org.dromara.hutool.extra.tokenizer.engine;
|
||||
|
||||
import org.dromara.hutool.core.lang.Singleton;
|
||||
import org.dromara.hutool.core.util.ServiceLoaderUtil;
|
||||
import org.dromara.hutool.core.spi.ServiceLoaderUtil;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.extra.tokenizer.TokenizerEngine;
|
||||
import org.dromara.hutool.extra.tokenizer.TokenizerException;
|
||||
|
@ -14,7 +14,7 @@ package org.dromara.hutool.http.client.engine;
|
||||
|
||||
import org.dromara.hutool.core.lang.Singleton;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.util.ServiceLoaderUtil;
|
||||
import org.dromara.hutool.core.spi.ServiceLoaderUtil;
|
||||
import org.dromara.hutool.http.HttpException;
|
||||
import org.dromara.hutool.http.client.ClientConfig;
|
||||
import org.dromara.hutool.http.client.ClientEngine;
|
||||
|
@ -15,7 +15,7 @@ package org.dromara.hutool.log;
|
||||
import org.dromara.hutool.core.io.resource.ResourceUtil;
|
||||
import org.dromara.hutool.core.lang.caller.CallerUtil;
|
||||
import org.dromara.hutool.core.map.SafeConcurrentHashMap;
|
||||
import org.dromara.hutool.core.util.ServiceLoaderUtil;
|
||||
import org.dromara.hutool.core.spi.ServiceLoaderUtil;
|
||||
import org.dromara.hutool.log.engine.console.ConsoleLogFactory;
|
||||
import org.dromara.hutool.log.engine.jdk.JdkLogFactory;
|
||||
|
||||
|
@ -201,7 +201,7 @@ public final class Props extends Properties implements TypeGetter<CharSequence>
|
||||
public void load(final Resource resource) {
|
||||
Assert.notNull(resource, "Props resource must be not null!");
|
||||
this.resource = resource;
|
||||
PropsLoaderUtil.loadTo(this, resource, this.charset);
|
||||
ResourceUtil.loadTo(this, resource, this.charset);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,73 +0,0 @@
|
||||
/*
|
||||
* 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:
|
||||
* http://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.setting.dialect;
|
||||
|
||||
import org.dromara.hutool.core.io.IORuntimeException;
|
||||
import org.dromara.hutool.core.io.resource.Resource;
|
||||
import org.dromara.hutool.core.io.resource.ResourceUtil;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* {@link Properties} 资源内容加载工具
|
||||
*
|
||||
* @author looly
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public class PropsLoaderUtil {
|
||||
|
||||
/**
|
||||
* 加载配置文件内容到{@link Properties}中<br>
|
||||
* 需要注意的是,如果资源文件的扩展名是.xml,会调用{@link Properties#loadFromXML(InputStream)} 读取。
|
||||
*
|
||||
* @param properties {@link Properties}文件
|
||||
* @param resource 资源
|
||||
* @param charset 编码,对XML无效
|
||||
*/
|
||||
public static void loadTo(final Properties properties, final Resource resource, final Charset charset) {
|
||||
final String filename = resource.getName();
|
||||
if (filename != null && filename.endsWith(".xml")) {
|
||||
// XML
|
||||
try (final InputStream in = resource.getStream()) {
|
||||
properties.loadFromXML(in);
|
||||
} catch (final IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
// .properties
|
||||
try (final BufferedReader reader = resource.getReader(charset)) {
|
||||
properties.load(reader);
|
||||
} catch (final IOException e) {
|
||||
throw new IORuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载指定名称的所有配置文件内容到{@link Properties}中
|
||||
*
|
||||
* @param properties {@link Properties}文件
|
||||
* @param resourceName 资源名,可以是相对classpath的路径,也可以是绝对路径
|
||||
* @param classLoader {@link ClassLoader},{@code null}表示使用默认的当前上下文ClassLoader
|
||||
* @param charset 编码,对XML无效
|
||||
*/
|
||||
public static void loadAllTo(final Properties properties, final String resourceName, final ClassLoader classLoader, final Charset charset) {
|
||||
for (final Resource resource : ResourceUtil.getResources(resourceName, classLoader)) {
|
||||
loadTo(properties, resource, charset);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user