mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-04-19 03:01:48 +08:00
fix code
This commit is contained in:
parent
b921895917
commit
56c076d2f6
@ -28,6 +28,16 @@ import java.lang.reflect.Method;
|
||||
*/
|
||||
public class MethodInvoker implements Invoker {
|
||||
|
||||
/**
|
||||
* 创建方法调用器
|
||||
*
|
||||
* @param method 方法
|
||||
* @return 方法调用器
|
||||
*/
|
||||
public static MethodInvoker of(final Method method) {
|
||||
return new MethodInvoker(method);
|
||||
}
|
||||
|
||||
private final Method method;
|
||||
private final Class<?>[] paramTypes;
|
||||
private final Class<?> type;
|
||||
@ -43,6 +53,7 @@ public class MethodInvoker implements Invoker {
|
||||
|
||||
this.paramTypes = method.getParameterTypes();
|
||||
if (paramTypes.length == 1) {
|
||||
// setter方法读取参数类型
|
||||
type = paramTypes[0];
|
||||
} else {
|
||||
type = method.getReturnType();
|
||||
@ -64,27 +75,44 @@ public class MethodInvoker implements Invoker {
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T invoke(final Object target, final Object... args) throws HutoolException{
|
||||
public <T> T invoke(Object target, final Object... args) throws HutoolException{
|
||||
if(this.checkArgs){
|
||||
checkArgs(args);
|
||||
}
|
||||
|
||||
final Method method = this.method;
|
||||
// static方法调用则target为null
|
||||
if(ModifierUtil.isStatic(method)){
|
||||
target = null;
|
||||
}
|
||||
// 根据方法定义的参数类型,将用户传入的参数规整和转换
|
||||
final Object[] actualArgs = MethodUtil.actualArgs(method, args);
|
||||
try {
|
||||
return MethodHandleUtil.invoke(target, method, args);
|
||||
return MethodHandleUtil.invokeExact(target, method, actualArgs);
|
||||
} catch (final Exception e) {
|
||||
// 传统反射方式执行方法
|
||||
try {
|
||||
return (T) method.invoke(ModifierUtil.isStatic(method) ? null : target, MethodUtil.actualArgs(method, args));
|
||||
return (T) method.invoke(target, actualArgs);
|
||||
} catch (final IllegalAccessException | InvocationTargetException ex) {
|
||||
throw new HutoolException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行静态方法
|
||||
*
|
||||
* @param <T> 对象类型
|
||||
* @param args 参数对象
|
||||
* @return 结果
|
||||
* @throws HutoolException 多种异常包装
|
||||
*/
|
||||
public <T> T invokeStatic(final Object... args) throws HutoolException {
|
||||
return invoke(null, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getType() {
|
||||
return this.type;
|
||||
|
@ -45,6 +45,13 @@ public class MethodUtil {
|
||||
*/
|
||||
private static final WeakConcurrentMap<Class<?>, MethodReflect> METHODS_CACHE = new WeakConcurrentMap<>();
|
||||
|
||||
/**
|
||||
* 清除方法缓存
|
||||
*/
|
||||
synchronized static void clearCache() {
|
||||
METHODS_CACHE.clear();
|
||||
}
|
||||
|
||||
// region ----- getMethods
|
||||
|
||||
/**
|
||||
@ -255,7 +262,7 @@ public class MethodUtil {
|
||||
/**
|
||||
* 获得一个类中所有方法列表,包括其父类中的方法
|
||||
*
|
||||
* @param clazz 类,非{@code null}
|
||||
* @param clazz 类,非{@code null}
|
||||
* @param predicate 方法过滤器,{@code null}表示无过滤
|
||||
* @return 方法列表
|
||||
* @throws SecurityException 安全检查异常
|
||||
@ -267,7 +274,7 @@ public class MethodUtil {
|
||||
/**
|
||||
* 获得本类及其父类所有Public方法
|
||||
*
|
||||
* @param clazz 查找方法的类
|
||||
* @param clazz 查找方法的类
|
||||
* @return 过滤后的方法列表
|
||||
*/
|
||||
public static Method[] getPublicMethods(final Class<?> clazz) {
|
||||
@ -288,7 +295,7 @@ public class MethodUtil {
|
||||
/**
|
||||
* 获得类中所有直接声明方法,不包括其父类中的方法
|
||||
*
|
||||
* @param clazz 类,非{@code null}
|
||||
* @param clazz 类,非{@code null}
|
||||
* @return 方法列表
|
||||
* @throws SecurityException 安全检查异常
|
||||
*/
|
||||
@ -529,7 +536,7 @@ public class MethodUtil {
|
||||
* @throws HutoolException 一些列异常的包装
|
||||
*/
|
||||
public static <T> T invokeWithCheck(final Object obj, final Method method, final Object... args) throws HutoolException {
|
||||
return (new MethodInvoker(method)).setCheckArgs(true).invoke(obj, args);
|
||||
return MethodInvoker.of(method).setCheckArgs(true).invoke(obj, args);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -553,7 +560,7 @@ public class MethodUtil {
|
||||
* @see MethodHandleUtil#invoke(Object, Method, Object...)
|
||||
*/
|
||||
public static <T> T invoke(final Object obj, final Method method, final Object... args) throws HutoolException {
|
||||
return (new MethodInvoker(method)).invoke(obj, args);
|
||||
return MethodInvoker.of(method).invoke(obj, args);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -26,7 +26,7 @@ import java.util.Map;
|
||||
public class ConstructorUtilTest {
|
||||
@Test
|
||||
public void noneStaticInnerClassTest() {
|
||||
final ReflectUtilTest.NoneStaticClass testAClass = ConstructorUtil.newInstanceIfPossible(ReflectUtilTest.NoneStaticClass.class);
|
||||
final ReflectTestBeans.NoneStaticClass testAClass = ConstructorUtil.newInstanceIfPossible(ReflectTestBeans.NoneStaticClass.class);
|
||||
Assertions.assertNotNull(testAClass);
|
||||
Assertions.assertEquals(2, testAClass.getA());
|
||||
}
|
||||
|
@ -22,34 +22,34 @@ public class FieldUtilTest {
|
||||
@Test
|
||||
public void getFieldTest() {
|
||||
// 能够获取到父类字段
|
||||
final Field privateField = FieldUtil.getField(ReflectUtilTest.TestSubClass.class, "privateField");
|
||||
final Field privateField = FieldUtil.getField(ReflectTestBeans.TestSubClass.class, "privateField");
|
||||
Assertions.assertNotNull(privateField);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getFieldsTest() {
|
||||
// 能够获取到父类字段
|
||||
final Field[] fields = FieldUtil.getFields(ReflectUtilTest.TestSubClass.class);
|
||||
final Field[] fields = FieldUtil.getFields(ReflectTestBeans.TestSubClass.class);
|
||||
Assertions.assertEquals(4, fields.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void setFieldTest() {
|
||||
final ReflectUtilTest.AClass testClass = new ReflectUtilTest.AClass();
|
||||
final ReflectTestBeans.AClass testClass = new ReflectTestBeans.AClass();
|
||||
FieldUtil.setFieldValue(testClass, "a", "111");
|
||||
Assertions.assertEquals(111, testClass.getA());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDeclaredField() {
|
||||
final Field noField = FieldUtil.getField(ReflectUtilTest.TestSubClass.class, "noField");
|
||||
final Field noField = FieldUtil.getField(ReflectTestBeans.TestSubClass.class, "noField");
|
||||
Assertions.assertNull(noField);
|
||||
|
||||
// 获取不到父类字段
|
||||
final Field field = FieldUtil.getDeclearField(ReflectUtilTest.TestSubClass.class, "field");
|
||||
final Field field = FieldUtil.getDeclearField(ReflectTestBeans.TestSubClass.class, "field");
|
||||
Assertions.assertNull(field);
|
||||
|
||||
final Field subField = FieldUtil.getField(ReflectUtilTest.TestSubClass.class, "subField");
|
||||
final Field subField = FieldUtil.getField(ReflectTestBeans.TestSubClass.class, "subField");
|
||||
Assertions.assertNotNull(subField);
|
||||
}
|
||||
|
||||
|
@ -78,6 +78,20 @@ public class MethodHandleUtilTest {
|
||||
Assertions.assertEquals("Duck 78", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvokeExact() {
|
||||
final Duck duck = new BigDuck();
|
||||
|
||||
final Method method = MethodUtil.getMethod(BigDuck.class, "toString");
|
||||
final Object[] args = {};
|
||||
|
||||
// 执行测试方法
|
||||
final String result = MethodHandleUtil.invokeExact(duck, method, args);
|
||||
|
||||
// 验证结果
|
||||
Assertions.assertEquals(duck.toString(), result);
|
||||
}
|
||||
|
||||
interface Duck {
|
||||
default String quack() {
|
||||
return "Quack";
|
||||
@ -102,5 +116,10 @@ public class MethodHandleUtilTest {
|
||||
private static String getPrivateStaticValue(){
|
||||
return "private static value";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,14 +15,14 @@ package org.dromara.hutool.core.reflect;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 反射工具类单元测试
|
||||
* 反射工具用于测试的类
|
||||
*
|
||||
* @author Looly
|
||||
*/
|
||||
public class ReflectUtilTest {
|
||||
public class ReflectTestBeans {
|
||||
|
||||
@Data
|
||||
static class AClass {
|
||||
protected static class AClass {
|
||||
private int a;
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ public class ReflectUtilTest {
|
||||
}
|
||||
|
||||
@Data
|
||||
static class TestBenchClass {
|
||||
protected static class TestBenchClass {
|
||||
private int a;
|
||||
private String b;
|
||||
private String c;
|
||||
@ -69,7 +69,7 @@ public class ReflectUtilTest {
|
||||
void getB();
|
||||
}
|
||||
|
||||
interface TestInterface3 extends TestInterface2 {
|
||||
protected interface TestInterface3 extends TestInterface2 {
|
||||
void get3();
|
||||
}
|
||||
|
||||
@ -88,7 +88,7 @@ public class ReflectUtilTest {
|
||||
}
|
||||
|
||||
@SuppressWarnings("RedundantMethodOverride")
|
||||
class C2 extends C1 {
|
||||
protected class C2 extends C1 {
|
||||
@Override
|
||||
public void getA() {
|
||||
|
||||
@ -108,7 +108,7 @@ public class ReflectUtilTest {
|
||||
}
|
||||
|
||||
@SuppressWarnings({"InnerClassMayBeStatic", "unused"})
|
||||
class TestSubClass extends TestClass {
|
||||
protected class TestSubClass extends TestClass {
|
||||
private String subField;
|
||||
|
||||
private void privateSubMethod() {
|
@ -1,294 +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:
|
||||
* 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.method;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import org.dromara.hutool.core.annotation.Alias;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* test for {@link MethodScanner2}
|
||||
*
|
||||
* @author huangchengxing
|
||||
*/
|
||||
class MethodScannerTest {
|
||||
|
||||
@Test
|
||||
void testGetMethods() {
|
||||
Assertions.assertEquals(0, MethodScanner2.getMethods(null).length);
|
||||
final Method[] actual = MethodScanner2.getMethods(Child.class);
|
||||
Assertions.assertSame(actual, MethodScanner2.getMethods(Child.class));
|
||||
final Method[] expected = Child.class.getMethods();
|
||||
Assertions.assertArrayEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetDeclaredMethods() {
|
||||
Assertions.assertEquals(0, MethodScanner2.getDeclaredMethods(null).length);
|
||||
final Method[] actual = MethodScanner2.getDeclaredMethods(Child.class);
|
||||
Assertions.assertSame(actual, MethodScanner2.getDeclaredMethods(Child.class));
|
||||
final Method[] expected = Child.class.getDeclaredMethods();
|
||||
Assertions.assertArrayEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetAllMethods() {
|
||||
Assertions.assertEquals(0, MethodScanner2.getAllMethods(null).length);
|
||||
final Method[] actual = MethodScanner2.getAllMethods(Child.class);
|
||||
// get declared method from child、parent、grandparent
|
||||
final Method[] expected = Stream.of(Child.class, Parent.class, Interface.class, Object.class)
|
||||
.flatMap(c -> Stream.of(MethodScanner2.getDeclaredMethods(c)))
|
||||
.toArray(Method[]::new);
|
||||
Assertions.assertArrayEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testClearCaches() {
|
||||
final Method[] declaredMethods = MethodScanner2.getDeclaredMethods(Child.class);
|
||||
Assertions.assertSame(declaredMethods, MethodScanner2.getDeclaredMethods(Child.class));
|
||||
final Method[] methods = MethodScanner2.getMethods(Child.class);
|
||||
Assertions.assertSame(methods, MethodScanner2.getMethods(Child.class));
|
||||
|
||||
// clear method cache
|
||||
MethodScanner2.clearCaches();
|
||||
Assertions.assertNotSame(declaredMethods, MethodScanner2.getDeclaredMethods(Child.class));
|
||||
Assertions.assertNotSame(methods, MethodScanner2.getMethods(Child.class));
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Test
|
||||
void testFindWithMetadataFromSpecificMethods() {
|
||||
Assertions.assertTrue(MethodScanner2.findWithMetadataFromSpecificMethods(null, m -> m.getAnnotation(Annotation.class)).isEmpty());
|
||||
final Method[] methods = MethodScanner2.getMethods(Child.class);
|
||||
final Map<Method, Annotation> actual = MethodScanner2.findWithMetadataFromSpecificMethods(methods, m -> m.getAnnotation(Annotation.class));
|
||||
Assertions.assertEquals(1, actual.size());
|
||||
|
||||
// check method
|
||||
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
|
||||
Assertions.assertTrue(actual.containsKey(expectedMethod));
|
||||
|
||||
// check annotation
|
||||
final Annotation expectedAnnotation = expectedMethod.getAnnotation(Annotation.class);
|
||||
Assertions.assertEquals(expectedAnnotation, actual.get(expectedMethod));
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Test
|
||||
void testFindFromSpecificMethods() {
|
||||
final Method[] methods = MethodScanner2.getMethods(Child.class);
|
||||
final Set<Method> actual = MethodScanner2.findFromSpecificMethods(methods, m -> m.getAnnotation(Annotation.class));
|
||||
Assertions.assertEquals(1, actual.size());
|
||||
|
||||
// check method
|
||||
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
|
||||
Assertions.assertTrue(actual.contains(expectedMethod));
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Test
|
||||
void testGetWithMetadataFromSpecificMethods() {
|
||||
// find first oneArgMethod method
|
||||
final Method[] methods = MethodScanner2.getMethods(Child.class);
|
||||
final Map.Entry<Method, Boolean> actual = MethodScanner2.getWithMetadataFromSpecificMethods(methods,
|
||||
(method -> method.getName().equals("oneArgMethod") ? true : null));
|
||||
Assertions.assertNotNull(actual);
|
||||
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
|
||||
Assertions.assertEquals(expectedMethod, actual.getKey());
|
||||
Assertions.assertTrue(actual.getValue());
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Test
|
||||
void testGetFromSpecificMethods() {
|
||||
// find first oneArgMethod method
|
||||
final Method[] methods = MethodScanner2.getMethods(Child.class);
|
||||
final Method actual = MethodScanner2.getFromSpecificMethods(methods, method ->
|
||||
method.getName().equals("oneArgMethod") ? true : null);
|
||||
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
|
||||
Assertions.assertEquals(expectedMethod, actual);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Test
|
||||
void testFindWithMetadataFromMethods() {
|
||||
final Map<Method, Annotation> actual = MethodScanner2.findWithMetadataFromMethods(Child.class, m -> m.getAnnotation(Annotation.class));
|
||||
Assertions.assertEquals(1, actual.size());
|
||||
|
||||
// check method
|
||||
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
|
||||
Assertions.assertTrue(actual.containsKey(expectedMethod));
|
||||
|
||||
// check annotation
|
||||
final Annotation expectedAnnotation = expectedMethod.getAnnotation(Annotation.class);
|
||||
Assertions.assertEquals(expectedAnnotation, actual.get(expectedMethod));
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Test
|
||||
void testFindFromMethods() {
|
||||
final Set<Method> actual = MethodScanner2.findFromMethods(Child.class, m -> m.getAnnotation(Annotation.class));
|
||||
Assertions.assertEquals(1, actual.size());
|
||||
|
||||
// check method
|
||||
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
|
||||
Assertions.assertTrue(actual.contains(expectedMethod));
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Test
|
||||
void testGetWithMetadataFromMethods() {
|
||||
final Map.Entry<Method, Annotation> actual = MethodScanner2.getWithMetadataFromMethods(Child.class, m -> m.getAnnotation(Annotation.class));
|
||||
Assertions.assertNotNull(actual);
|
||||
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
|
||||
Assertions.assertEquals(expectedMethod, actual.getKey());
|
||||
final Annotation expectedAnnotation = expectedMethod.getAnnotation(Annotation.class);
|
||||
Assertions.assertEquals(expectedAnnotation, actual.getValue());
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Test
|
||||
void testGetFromMethods() {
|
||||
final Method actual = MethodScanner2.getFromMethods(Child.class, m -> m.getAnnotation(Annotation.class));
|
||||
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
|
||||
Assertions.assertEquals(expectedMethod, actual);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Test
|
||||
void testFindWithMetadataFromDeclaredMethods() {
|
||||
final Map<Method, Annotation> actual = MethodScanner2.findWithMetadataFromDeclaredMethods(Parent.class, m -> m.getAnnotation(Annotation.class));
|
||||
Assertions.assertEquals(1, actual.size());
|
||||
|
||||
// check method
|
||||
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
|
||||
Assertions.assertTrue(actual.containsKey(expectedMethod));
|
||||
|
||||
// check annotation
|
||||
final Annotation expectedAnnotation = expectedMethod.getAnnotation(Annotation.class);
|
||||
Assertions.assertEquals(expectedAnnotation, actual.get(expectedMethod));
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Test
|
||||
void testFindFromDeclaredMethods() {
|
||||
final Set<Method> actual = MethodScanner2.findFromDeclaredMethods(Parent.class, m -> m.getAnnotation(Annotation.class));
|
||||
Assertions.assertEquals(1, actual.size());
|
||||
|
||||
// check method
|
||||
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
|
||||
Assertions.assertTrue(actual.contains(expectedMethod));
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Test
|
||||
void testGetWithMetadataFromDeclaredMethods() {
|
||||
final Map.Entry<Method, Annotation> actual = MethodScanner2.getWithMetadataFromDeclaredMethods(Parent.class, m -> m.getAnnotation(Annotation.class));
|
||||
Assertions.assertNotNull(actual);
|
||||
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
|
||||
Assertions.assertEquals(expectedMethod, actual.getKey());
|
||||
final Annotation expectedAnnotation = expectedMethod.getAnnotation(Annotation.class);
|
||||
Assertions.assertEquals(expectedAnnotation, actual.getValue());
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Test
|
||||
void testGetFromDeclaredMethods() {
|
||||
final Method actual = MethodScanner2.getFromDeclaredMethods(Parent.class, m -> m.getAnnotation(Annotation.class));
|
||||
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
|
||||
Assertions.assertEquals(expectedMethod, actual);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Test
|
||||
void testFindWithMetadataFromAllMethods() {
|
||||
final Map<Method, Annotation> actual = MethodScanner2.findWithMetadataFromAllMethods(Child.class, m -> m.getAnnotation(Annotation.class));
|
||||
Assertions.assertEquals(1, actual.size());
|
||||
|
||||
// check method
|
||||
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
|
||||
Assertions.assertTrue(actual.containsKey(expectedMethod));
|
||||
|
||||
// check annotation
|
||||
final Annotation expectedAnnotation = expectedMethod.getAnnotation(Annotation.class);
|
||||
Assertions.assertEquals(expectedAnnotation, actual.get(expectedMethod));
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Test
|
||||
void testFindFromAllMethods() {
|
||||
final Set<Method> actual = MethodScanner2.findFromAllMethods(Child.class, m -> m.getAnnotation(Annotation.class));
|
||||
Assertions.assertEquals(1, actual.size());
|
||||
|
||||
// check method
|
||||
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
|
||||
Assertions.assertTrue(actual.contains(expectedMethod));
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Test
|
||||
void testGetWithMetadataFromAllMethods() {
|
||||
Assertions.assertNull(MethodScanner2.getWithMetadataFromAllMethods(Child.class, m -> m.getAnnotation(Alias.class)));
|
||||
final Map.Entry<Method, Annotation> actual = MethodScanner2.getWithMetadataFromAllMethods(Child.class, m -> m.getAnnotation(Annotation.class));
|
||||
Assertions.assertNotNull(actual);
|
||||
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
|
||||
Assertions.assertEquals(expectedMethod, actual.getKey());
|
||||
final Annotation expectedAnnotation = expectedMethod.getAnnotation(Annotation.class);
|
||||
Assertions.assertEquals(expectedAnnotation, actual.getValue());
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
@Test
|
||||
void testGetFromAllMethods() {
|
||||
final Method actual = MethodScanner2.getFromAllMethods(Child.class, m -> m.getAnnotation(Annotation.class));
|
||||
final Method expectedMethod = Parent.class.getDeclaredMethod("oneArgMethod", String.class);
|
||||
Assertions.assertEquals(expectedMethod, actual);
|
||||
}
|
||||
|
||||
@Target({ElementType.METHOD, ElementType.TYPE, ElementType.ANNOTATION_TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Annotation {
|
||||
String value() default "default";
|
||||
}
|
||||
|
||||
@Annotation("Interface")
|
||||
public interface Interface {
|
||||
static void staticMethod() {
|
||||
|
||||
}
|
||||
void noneArgMethod();
|
||||
void oneArgMethod(String arg);
|
||||
}
|
||||
|
||||
public static class Parent implements Interface {
|
||||
@Override
|
||||
public void noneArgMethod() { }
|
||||
|
||||
@Annotation("oneArgMethod")
|
||||
@Override
|
||||
public void oneArgMethod(final String arg) { }
|
||||
}
|
||||
|
||||
public static class Child extends Parent implements Interface {
|
||||
|
||||
}
|
||||
}
|
@ -10,14 +10,15 @@
|
||||
* See the Mulan PSL v2 for more details.
|
||||
*/
|
||||
|
||||
package org.dromara.hutool.core.reflect;
|
||||
package org.dromara.hutool.core.reflect.method;
|
||||
|
||||
import lombok.Data;
|
||||
import org.dromara.hutool.core.array.ArrayUtil;
|
||||
import org.dromara.hutool.core.date.StopWatch;
|
||||
import org.dromara.hutool.core.lang.Console;
|
||||
import org.dromara.hutool.core.lang.test.bean.ExamInfoDict;
|
||||
import org.dromara.hutool.core.reflect.method.MethodUtil;
|
||||
import org.dromara.hutool.core.reflect.ClassUtil;
|
||||
import org.dromara.hutool.core.reflect.ReflectTestBeans;
|
||||
import org.dromara.hutool.core.text.StrUtil;
|
||||
import org.dromara.hutool.core.util.JdkUtil;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
@ -26,7 +27,7 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class MethodUtilTest {
|
||||
public class MethodUtilTest extends ReflectTestBeans {
|
||||
|
||||
private static final boolean isGteJdk15 = getJavaVersion() >= 15;
|
||||
/**
|
||||
@ -87,14 +88,14 @@ public class MethodUtilTest {
|
||||
|
||||
@Test
|
||||
public void invokeTest() {
|
||||
final ReflectUtilTest.AClass testClass = new ReflectUtilTest.AClass();
|
||||
final AClass testClass = new AClass();
|
||||
MethodUtil.invoke(testClass, "setA", 10);
|
||||
Assertions.assertEquals(10, testClass.getA());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDeclaredMethodsTest() {
|
||||
Class<?> type = ReflectUtilTest.TestBenchClass.class;
|
||||
Class<?> type = TestBenchClass.class;
|
||||
Method[] methods = type.getDeclaredMethods();
|
||||
Assertions.assertArrayEquals(methods, MethodUtil.getDeclaredMethods(type));
|
||||
Assertions.assertSame(MethodUtil.getDeclaredMethods(type), MethodUtil.getDeclaredMethods(type));
|
||||
@ -108,19 +109,19 @@ public class MethodUtilTest {
|
||||
@Disabled
|
||||
public void getMethodBenchTest() {
|
||||
// 预热
|
||||
getMethodWithReturnTypeCheck(ReflectUtilTest.TestBenchClass.class, false, "getH");
|
||||
getMethodWithReturnTypeCheck(TestBenchClass.class, false, "getH");
|
||||
|
||||
final StopWatch timer = new StopWatch();
|
||||
timer.start();
|
||||
for (int i = 0; i < 100000000; i++) {
|
||||
MethodUtil.getMethod(ReflectUtilTest.TestBenchClass.class, false, "getH");
|
||||
MethodUtil.getMethod(TestBenchClass.class, false, "getH");
|
||||
}
|
||||
timer.stop();
|
||||
Console.log(timer.getLastTaskTimeMillis());
|
||||
|
||||
timer.start();
|
||||
for (int i = 0; i < 100000000; i++) {
|
||||
getMethodWithReturnTypeCheck(ReflectUtilTest.TestBenchClass.class, false, "getH");
|
||||
getMethodWithReturnTypeCheck(TestBenchClass.class, false, "getH");
|
||||
}
|
||||
timer.stop();
|
||||
Console.log(timer.getLastTaskTimeMillis());
|
||||
@ -150,60 +151,60 @@ public class MethodUtilTest {
|
||||
@Test
|
||||
public void getMethodsFromClassExtends() {
|
||||
// 继承情况下,需解决方法去重问题
|
||||
Method[] methods = MethodUtil.getMethods(ReflectUtilTest.C2.class);
|
||||
Method[] methods = MethodUtil.getMethods(C2.class);
|
||||
Assertions.assertEquals(isGteJdk15 ? 14 : 15, methods.length);
|
||||
|
||||
// 排除Object中的方法
|
||||
// 3个方法包括类
|
||||
methods = MethodUtil.getMethodsDirectly(ReflectUtilTest.C2.class, true, false);
|
||||
methods = MethodUtil.getMethodsDirectly(C2.class, true, false);
|
||||
Assertions.assertEquals(3, methods.length);
|
||||
|
||||
// getA属于本类
|
||||
Assertions.assertEquals("public void org.dromara.hutool.core.reflect.ReflectUtilTest$C2.getA()", methods[0].toString());
|
||||
Assertions.assertEquals("public void org.dromara.hutool.core.reflect.ReflectTestBeans$C2.getA()", methods[0].toString());
|
||||
// getB属于父类
|
||||
Assertions.assertEquals("public void org.dromara.hutool.core.reflect.ReflectUtilTest$C1.getB()", methods[1].toString());
|
||||
Assertions.assertEquals("public void org.dromara.hutool.core.reflect.ReflectTestBeans$C1.getB()", methods[1].toString());
|
||||
// getC属于接口中的默认方法
|
||||
Assertions.assertEquals("public default void org.dromara.hutool.core.reflect.ReflectUtilTest$TestInterface1.getC()", methods[2].toString());
|
||||
Assertions.assertEquals("public default void org.dromara.hutool.core.reflect.ReflectTestBeans$TestInterface1.getC()", methods[2].toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMethodsFromInterfaceTest() {
|
||||
// 对于接口,直接调用Class.getMethods方法获取所有方法,因为接口都是public方法
|
||||
// 因此此处得到包括TestInterface1、TestInterface2、TestInterface3中一共4个方法
|
||||
final Method[] methods = MethodUtil.getMethods(ReflectUtilTest.TestInterface3.class);
|
||||
final Method[] methods = MethodUtil.getMethods(TestInterface3.class);
|
||||
Assertions.assertEquals(4, methods.length);
|
||||
|
||||
// 接口里,调用getMethods和getPublicMethods效果相同
|
||||
final Method[] publicMethods = MethodUtil.getPublicMethods(ReflectUtilTest.TestInterface3.class);
|
||||
final Method[] publicMethods = MethodUtil.getPublicMethods(TestInterface3.class);
|
||||
Assertions.assertArrayEquals(methods, publicMethods);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getPublicMethod() {
|
||||
final Method superPublicMethod = MethodUtil.getPublicMethod(ReflectUtilTest.TestSubClass.class, false, "publicMethod");
|
||||
final Method superPublicMethod = MethodUtil.getPublicMethod(TestSubClass.class, false, "publicMethod");
|
||||
Assertions.assertNotNull(superPublicMethod);
|
||||
final Method superPrivateMethod = MethodUtil.getPublicMethod(ReflectUtilTest.TestSubClass.class, false, "privateMethod");
|
||||
final Method superPrivateMethod = MethodUtil.getPublicMethod(TestSubClass.class, false, "privateMethod");
|
||||
Assertions.assertNull(superPrivateMethod);
|
||||
|
||||
final Method publicMethod = MethodUtil.getPublicMethod(ReflectUtilTest.TestSubClass.class, false, "publicSubMethod");
|
||||
final Method publicMethod = MethodUtil.getPublicMethod(TestSubClass.class, false, "publicSubMethod");
|
||||
Assertions.assertNotNull(publicMethod);
|
||||
final Method privateMethod = MethodUtil.getPublicMethod(ReflectUtilTest.TestSubClass.class, false, "privateSubMethod");
|
||||
final Method privateMethod = MethodUtil.getPublicMethod(TestSubClass.class, false, "privateSubMethod");
|
||||
Assertions.assertNull(privateMethod);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDeclaredMethod() {
|
||||
final Method noMethod = MethodUtil.getMethod(ReflectUtilTest.TestSubClass.class, "noMethod");
|
||||
final Method noMethod = MethodUtil.getMethod(TestSubClass.class, "noMethod");
|
||||
Assertions.assertNull(noMethod);
|
||||
|
||||
final Method privateMethod = MethodUtil.getMethod(ReflectUtilTest.TestSubClass.class, "privateMethod");
|
||||
final Method privateMethod = MethodUtil.getMethod(TestSubClass.class, "privateMethod");
|
||||
Assertions.assertNotNull(privateMethod);
|
||||
final Method publicMethod = MethodUtil.getMethod(ReflectUtilTest.TestSubClass.class, "publicMethod");
|
||||
final Method publicMethod = MethodUtil.getMethod(TestSubClass.class, "publicMethod");
|
||||
Assertions.assertNotNull(publicMethod);
|
||||
|
||||
final Method publicSubMethod = MethodUtil.getMethod(ReflectUtilTest.TestSubClass.class, "publicSubMethod");
|
||||
final Method publicSubMethod = MethodUtil.getMethod(TestSubClass.class, "publicSubMethod");
|
||||
Assertions.assertNotNull(publicSubMethod);
|
||||
final Method privateSubMethod = MethodUtil.getMethod(ReflectUtilTest.TestSubClass.class, "privateSubMethod");
|
||||
final Method privateSubMethod = MethodUtil.getMethod(TestSubClass.class, "privateSubMethod");
|
||||
Assertions.assertNotNull(privateSubMethod);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user