This commit is contained in:
Looly 2023-05-04 00:51:31 +08:00
parent b92c91a134
commit b6f970ce20
10 changed files with 342 additions and 17 deletions

View File

@ -30,6 +30,22 @@
<properties> <properties>
<Automatic-Module-Name>org.dromara.hutool.core</Automatic-Module-Name> <Automatic-Module-Name>org.dromara.hutool.core</Automatic-Module-Name>
<kotlin-version>1.8.21</kotlin-version>
</properties> </properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin-version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
<version>${kotlin-version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</project> </project>

View File

@ -16,8 +16,6 @@ import org.dromara.hutool.core.exception.HutoolException;
import org.dromara.hutool.core.reflect.ClassDescUtil; import org.dromara.hutool.core.reflect.ClassDescUtil;
import java.io.File; import java.io.File;
import java.security.AccessController;
import java.security.PrivilegedAction;
/** /**
* {@link ClassLoader}工具类<br> * {@link ClassLoader}工具类<br>
@ -58,13 +56,7 @@ public class ClassLoaderUtil {
* @see Thread#getContextClassLoader() * @see Thread#getContextClassLoader()
*/ */
public static ClassLoader getContextClassLoader() { public static ClassLoader getContextClassLoader() {
if (System.getSecurityManager() == null) { return Thread.currentThread().getContextClassLoader();
return Thread.currentThread().getContextClassLoader();
} else {
// 绕开权限检查
return AccessController.doPrivileged(
(PrivilegedAction<ClassLoader>) () -> Thread.currentThread().getContextClassLoader());
}
} }
/** /**
@ -75,13 +67,7 @@ public class ClassLoaderUtil {
* @since 5.7.0 * @since 5.7.0
*/ */
public static ClassLoader getSystemClassLoader() { public static ClassLoader getSystemClassLoader() {
if (System.getSecurityManager() == null) { return ClassLoader.getSystemClassLoader();
return ClassLoader.getSystemClassLoader();
} else {
// 绕开权限检查
return AccessController.doPrivileged(
(PrivilegedAction<ClassLoader>) ClassLoader::getSystemClassLoader);
}
} }
/** /**

View File

@ -72,7 +72,7 @@ public class Opt<T> {
*/ */
public static <T> Opt<T> ofNullable(final T value) { public static <T> Opt<T> ofNullable(final T value) {
return value == null ? empty() return value == null ? empty()
: new Opt<>(value); : new Opt<>(value);
} }
/** /**

View File

@ -0,0 +1,49 @@
/*
* 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.reflect.kotlin;
import org.dromara.hutool.core.classloader.ClassLoaderUtil;
import org.dromara.hutool.core.reflect.MethodUtil;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/**
* kotlin.reflect.KCallable方法包装调用类
*
* @author VampireAchao, Looly
*/
public class KCallable {
private static final Method METHOD_GET_PARAMETERS;
static {
final Class<?> kFunctionClass = ClassLoaderUtil.loadClass("kotlin.reflect.KCallable");
METHOD_GET_PARAMETERS = MethodUtil.getMethod(kFunctionClass, "getParameters");
}
/**
* 获取参数列表
*
* @param kCallable kotlin的类方法或构造
* @return 参数列表
*/
public static List<KParameter> getParameters(final Object kCallable) {
final List<?> parameters = MethodUtil.invoke(kCallable, METHOD_GET_PARAMETERS);
final List<KParameter> result = new ArrayList<>(parameters.size());
for (final Object parameter : parameters) {
result.add(new KParameter(parameter));
}
return result;
}
}

View File

@ -0,0 +1,46 @@
/*
* 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.reflect.kotlin;
import org.dromara.hutool.core.classloader.ClassLoaderUtil;
import org.dromara.hutool.core.reflect.ConstructorUtil;
import org.dromara.hutool.core.reflect.MethodUtil;
import java.lang.reflect.Method;
import java.util.List;
/**
* kotlin.reflect.jvm.internal.KClassImpl包装
*
* @author VampireAchao, Looly
*/
public class KClassImpl {
private static final Class<?> KCLASS_IMPL_CLASS;
private static final Method METHOD_GET_CONSTRUCTORS;
static {
KCLASS_IMPL_CLASS = ClassLoaderUtil.loadClass("kotlin.reflect.jvm.internal.KClassImpl");
METHOD_GET_CONSTRUCTORS = MethodUtil.getMethod(KCLASS_IMPL_CLASS, "getConstructors");
}
/**
* 获取Kotlin类的所有构造方法
*
* @param targetType kotlin类
* @return 构造列表
*/
public static List<?> getConstructors(final Class<?> targetType) {
final Object kClassImpl = ConstructorUtil.newInstance(KCLASS_IMPL_CLASS, targetType);
return MethodUtil.invoke(kClassImpl, METHOD_GET_CONSTRUCTORS);
}
}

View File

@ -0,0 +1,51 @@
/*
* 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.reflect.kotlin;
import org.dromara.hutool.core.lang.Opt;
import java.util.List;
/**
* Kotlin反射包装相关工具类
*
* @author VampireAchao, Looly
*/
public class KClassUtil {
/**
* 是否提供或处于Kotlin环境中
*/
public static final boolean IS_KOTLIN_ENABLE =
Opt.ofTry(() -> Class.forName("kotlin.Metadata")).isPresent();
/**
* 获取Kotlin类的所有构造方法
*
* @param targetType kotlin类
* @return 构造列表
*/
public static List<?> getConstructors(final Class<?> targetType) {
return KClassImpl.getConstructors(targetType);
}
/**
* 获取参数列表
*
* @param kCallable kotlin的类方法或构造
* @return 参数列表
*/
public static List<KParameter> getParameters(final Object kCallable) {
return KCallable.getParameters(kCallable);
}
}

View File

@ -0,0 +1,98 @@
/*
* 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.reflect.kotlin;
import org.dromara.hutool.core.classloader.ClassLoaderUtil;
import org.dromara.hutool.core.reflect.MethodUtil;
import java.lang.reflect.Method;
import java.util.Objects;
/**
* kotlin.reflect.KParameter实例表示类<br>
* 通过反射获取Kotlin中KParameter相关属性值
*
* @author VampireAchao, Looly
*/
public class KParameter {
private static final Method METHOD_GET_NAME;
private static final Method METHOD_GET_TYPE;
private static final Method METHOD_GET_JAVA_TYPE;
static {
final Class<?> kParameterClass = ClassLoaderUtil.loadClass("kotlin.reflect.KParameter");
METHOD_GET_NAME = MethodUtil.getMethod(kParameterClass, "getName");
METHOD_GET_TYPE = MethodUtil.getMethod(kParameterClass, "getType");
final Class<?> kTypeClass = ClassLoaderUtil.loadClass("kotlin.reflect.jvm.internal.KTypeImpl");
METHOD_GET_JAVA_TYPE = MethodUtil.getMethod(kTypeClass, "getJavaType");
}
private final String name;
private final Class<?> type;
/**
* 构造
*
* @param kParameterInstance kotlin.reflect.KParameter实例对象
*/
public KParameter(final Object kParameterInstance) {
this.name = MethodUtil.invoke(kParameterInstance, METHOD_GET_NAME);
final Object kType = MethodUtil.invoke(kParameterInstance, METHOD_GET_TYPE);
this.type = MethodUtil.invoke(kType, METHOD_GET_JAVA_TYPE);
}
/**
* 获取参数名
*
* @return 参数名
*/
public String getName() {
return name;
}
/**
* 获取参数类型
*
* @return 参数类型
*/
public Class<?> getType() {
return type;
}
@Override
public boolean equals(final Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final KParameter that = (KParameter) o;
return Objects.equals(name, that.name) && Objects.equals(type, that.type);
}
@Override
public int hashCode() {
return Objects.hash(name, type);
}
@Override
public String toString() {
return "KParameter{" +
"name='" + name + '\'' +
", type=" + type +
'}';
}
}

View File

@ -0,0 +1,22 @@
/*
* 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.
*/
/**
* Kotlin反射相关封装需引入
* <ul>
* <li>kotlin-stdlib</li>
* <li>kotlin-reflect</li>
* </ul>
*
* @author VampireAchao, Looly
*/
package org.dromara.hutool.core.reflect.kotlin;

View File

@ -0,0 +1,42 @@
/*
* 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.reflect.kotlin;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.List;
public class KClassUtilTest {
@Test
void getConstructorTest() {
final List<?> constructors = KClassUtil.getConstructors(TestKBean.class);
Assertions.assertEquals(1, constructors.size());
Assertions.assertEquals("kotlin.reflect.jvm.internal.KFunctionImpl",
constructors.get(0).getClass().getName());
}
@Test
void getParametersTest() {
final List<?> constructors = KClassUtil.getConstructors(TestKBean.class);
final List<KParameter> parameters = KClassUtil.getParameters(constructors.get(0));
Assertions.assertEquals(3, parameters.size());
Assertions.assertEquals("id", parameters.get(0).getName());
Assertions.assertEquals("name", parameters.get(1).getName());
Assertions.assertEquals("country", parameters.get(2).getName());
}
}

View File

@ -0,0 +1,15 @@
/*
* 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.reflect.kotlin
data class TestKBean(val id: String, var name: String?, var country: String?)