This commit is contained in:
Looly 2023-03-25 06:34:07 +08:00
parent db96c981e3
commit dacb489c12
4 changed files with 51 additions and 26 deletions

View File

@ -6,6 +6,7 @@ import cn.hutool.core.lang.mutable.MutableEntry;
import cn.hutool.core.map.WeakConcurrentMap; import cn.hutool.core.map.WeakConcurrentMap;
import cn.hutool.core.reflect.LookupFactory; import cn.hutool.core.reflect.LookupFactory;
import cn.hutool.core.reflect.MethodUtil; import cn.hutool.core.reflect.MethodUtil;
import cn.hutool.core.reflect.ModifierUtil;
import cn.hutool.core.reflect.ReflectUtil; import cn.hutool.core.reflect.ReflectUtil;
import java.io.Serializable; import java.io.Serializable;
@ -13,7 +14,6 @@ import java.lang.invoke.*;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Executable; import java.lang.reflect.Executable;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -76,7 +76,7 @@ public class LambdaFactory {
final MutableEntry<Class<?>, Executable> cacheKey = new MutableEntry<>(functionInterfaceType, executable); final MutableEntry<Class<?>, Executable> cacheKey = new MutableEntry<>(functionInterfaceType, executable);
return (F) CACHE.computeIfAbsent(cacheKey, key -> { return (F) CACHE.computeIfAbsent(cacheKey, key -> {
final List<Method> abstractMethods = Arrays.stream(functionInterfaceType.getMethods()) final List<Method> abstractMethods = Arrays.stream(functionInterfaceType.getMethods())
.filter(m -> Modifier.isAbstract(m.getModifiers())) .filter(ModifierUtil::isAbstract)
.collect(Collectors.toList()); .collect(Collectors.toList());
Assert.equals(abstractMethods.size(), 1, "不支持非函数式接口"); Assert.equals(abstractMethods.size(), 1, "不支持非函数式接口");
ReflectUtil.setAccessible(executable); ReflectUtil.setAccessible(executable);

View File

@ -10,8 +10,12 @@ import java.lang.reflect.Method;
/** /**
* {@link MethodHandles.Lookup}工厂用于创建{@link MethodHandles.Lookup}对象<br> * {@link MethodHandles.Lookup}工厂用于创建{@link MethodHandles.Lookup}对象<br>
* {@link MethodHandles.Lookup}是一个方法句柄查找对象用于在指定类中查找符合给定方法名称方法类型的方法句柄
*
* <p>
* jdk8中如果直接调用{@link MethodHandles#lookup()}获取到的{@link MethodHandles.Lookup}在调用findSpecial和unreflectSpecial * jdk8中如果直接调用{@link MethodHandles#lookup()}获取到的{@link MethodHandles.Lookup}在调用findSpecial和unreflectSpecial
* 时会出现权限不够问题抛出"no private access for invokespecial"异常因此针对JDK8及JDK9+分别封装lookup方法 * 时会出现权限不够问题抛出"no private access for invokespecial"异常因此针对JDK8及JDK9+分别封装lookup方法
* </p>
* *
* <p> * <p>
* 参考 * 参考

View File

@ -12,9 +12,15 @@ import java.lang.reflect.Method;
/** /**
* 方法句柄{@link MethodHandle}封装工具类<br> * 方法句柄{@link MethodHandle}封装工具类<br>
* 方法句柄是一个有类型的可以直接执行的指向底层方法构造器field等的引用可以简单理解为函数指针它是一种更加底层的查找调整和调用方法的机制 * 方法句柄是一个有类型的可以直接执行的指向底层方法构造器field等的引用可以简单理解为函数指针它是一种更加底层的查找调整和调用方法的机制
*
* <p>
* {@link MethodHandle}类似于C/C++的函数指针用于模拟在字节码层次的方法调用且可以采用字节码优化优于反射
* </p>
* <p>
* 参考 * 参考
* <ul> * <ul>
* <li><a href="https://stackoverflow.com/questions/22614746/how-do-i-invoke-java-8-default-methods-reflectively">https://stackoverflow.com/questions/22614746/how-do-i-invoke-java-8-default-methods-reflectively</a></li> * <li><a href="https://stackoverflow.com/questions/22614746/how-do-i-invoke-java-8-default-methods-reflectively">
* https://stackoverflow.com/questions/22614746/how-do-i-invoke-java-8-default-methods-reflectively</a></li>
* </ul> * </ul>
* *
* @author looly * @author looly
@ -33,7 +39,7 @@ public class MethodHandleUtil {
* *
* @param callerClass 方法所在类或接口 * @param callerClass 方法所在类或接口
* @param name 方法名称{@code null}或者空则查找构造方法 * @param name 方法名称{@code null}或者空则查找构造方法
* @param type 返回类型和参数类型 * @param type 返回类型和参数类型可以使用{@code MethodType#methodType}构建
* @return 方法句柄 {@link MethodHandle}{@code null}表示未找到方法 * @return 方法句柄 {@link MethodHandle}{@code null}表示未找到方法
*/ */
public static MethodHandle findMethod(final Class<?> callerClass, final String name, final MethodType type) { public static MethodHandle findMethod(final Class<?> callerClass, final String name, final MethodType type) {
@ -101,6 +107,36 @@ public class MethodHandleUtil {
} }
} }
/**
* 执行方法句柄{@link MethodHandle#invoke(Object...)}包装<br>
*
* @param methodHandle {@link MethodHandle}
* @param args 方法参数值支持子类转换和自动拆装箱
* @param <T> 返回值类型
* @return 方法返回值
*/
@SuppressWarnings("unchecked")
public static <T> T invokeHandle(final MethodHandle methodHandle, final Object... args) {
try {
return (T) methodHandle.invoke(args);
} catch (final Throwable e) {
throw new RuntimeException(e);
}
}
/**
* 执行接口或对象中的方法
*
* @param <T> 返回结果类型
* @param obj 接口的子对象或代理对象
* @param method 方法
* @param args 参数
* @return 结果
*/
public static <T> T invoke(final Object obj, final Method method, final Object... args) {
return invoke(false, obj, method, args);
}
/** /**
* 执行接口或对象中的特殊方法privatestatic等<br> * 执行接口或对象中的特殊方法privatestatic等<br>
* *
@ -133,19 +169,6 @@ public class MethodHandleUtil {
return invokeSpecial(obj, method, args); return invokeSpecial(obj, method, args);
} }
/**
* 执行接口或对象中的方法
*
* @param <T> 返回结果类型
* @param obj 接口的子对象或代理对象
* @param method 方法
* @param args 参数
* @return 结果
*/
public static <T> T invoke(final Object obj, final Method method, final Object... args) {
return invoke(false, obj, method, args);
}
/** /**
* 执行接口或对象中的特殊方法privatestatic等<br> * 执行接口或对象中的特殊方法privatestatic等<br>
* *

View File

@ -127,7 +127,7 @@ public class ModifierUtil {
* @return 是否是Public * @return 是否是Public
*/ */
public static boolean isPublic(final Member member) { public static boolean isPublic(final Member member) {
return hasModifier(member, ModifierType.PUBLIC); return Modifier.isPublic(member.getModifiers());
} }
/** /**
@ -137,7 +137,7 @@ public class ModifierUtil {
* @return 是否是Public * @return 是否是Public
*/ */
public static boolean isPublic(final Class<?> clazz) { public static boolean isPublic(final Class<?> clazz) {
return hasModifier(clazz, ModifierType.PUBLIC); return Modifier.isPublic(clazz.getModifiers());
} }
/** /**
@ -148,7 +148,7 @@ public class ModifierUtil {
* @since 4.0.8 * @since 4.0.8
*/ */
public static boolean isStatic(final Member member) { public static boolean isStatic(final Member member) {
return hasModifier(member, ModifierType.STATIC); return Modifier.isStatic(member.getModifiers());
} }
/** /**
@ -159,7 +159,7 @@ public class ModifierUtil {
* @since 4.0.8 * @since 4.0.8
*/ */
public static boolean isStatic(final Class<?> clazz) { public static boolean isStatic(final Class<?> clazz) {
return hasModifier(clazz, ModifierType.STATIC); return Modifier.isStatic(clazz.getModifiers());
} }
/** /**
@ -192,7 +192,7 @@ public class ModifierUtil {
* @since 5.7.23 * @since 5.7.23
*/ */
public static boolean isAbstract(final Member member) { public static boolean isAbstract(final Member member) {
return hasModifier(member, ModifierType.ABSTRACT); return Modifier.isAbstract(member.getModifiers());
} }
/** /**
@ -203,7 +203,7 @@ public class ModifierUtil {
* @since 5.7.23 * @since 5.7.23
*/ */
public static boolean isAbstract(final Class<?> clazz) { public static boolean isAbstract(final Class<?> clazz) {
return hasModifier(clazz, ModifierType.ABSTRACT); return Modifier.isAbstract(clazz.getModifiers());
} }
/** /**
@ -251,9 +251,7 @@ public class ModifierUtil {
} }
//将字段的访问权限设为true即去除private修饰符的影响 //将字段的访问权限设为true即去除private修饰符的影响
if (false == field.isAccessible()) { ReflectUtil.setAccessible(field);
field.setAccessible(true);
}
try { try {
//去除final修饰符的影响将字段设为可修改的 //去除final修饰符的影响将字段设为可修改的
final Field modifiersField = Field.class.getDeclaredField("modifiers"); final Field modifiersField = Field.class.getDeclaredField("modifiers");