mirror of
https://github.com/continew-org/continew-starter.git
synced 2025-09-09 20:57:23 +08:00
feat(core): ReflectUtils 新增 createMethodReference 方法(由 CRUD 模块迁移)
This commit is contained in:
@@ -17,11 +17,17 @@
|
|||||||
package top.continew.starter.core.util;
|
package top.continew.starter.core.util;
|
||||||
|
|
||||||
import cn.hutool.core.util.ReflectUtil;
|
import cn.hutool.core.util.ReflectUtil;
|
||||||
|
import top.continew.starter.core.constant.StringConstants;
|
||||||
|
import top.continew.starter.core.exception.BusinessException;
|
||||||
|
|
||||||
|
import java.lang.invoke.MethodHandleProxies;
|
||||||
|
import java.lang.invoke.MethodHandles;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,4 +66,27 @@ public class ReflectUtils {
|
|||||||
Field[] fields = ReflectUtil.getFields(beanClass);
|
Field[] fields = ReflectUtil.getFields(beanClass);
|
||||||
return Arrays.stream(fields).filter(f -> !Modifier.isStatic(f.getModifiers())).collect(Collectors.toList());
|
return Arrays.stream(fields).filter(f -> !Modifier.isStatic(f.getModifiers())).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过反射创建方法引用,支持在父类中查找方法
|
||||||
|
*
|
||||||
|
* @param clazz 实体类类型
|
||||||
|
* @param methodName 方法名
|
||||||
|
* @param <T> 实体类类型
|
||||||
|
* @param <K> 返回值类型
|
||||||
|
* @return Function<T, K> 方法引用
|
||||||
|
* @throws IllegalArgumentException 如果参数不合法
|
||||||
|
* @author lishuyan
|
||||||
|
* @since 2.13.2
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static <T, K> Function<T, K> createMethodReference(Class<T> clazz, String methodName) {
|
||||||
|
try {
|
||||||
|
Method method = ReflectUtil.getMethodByName(clazz, methodName);
|
||||||
|
method.setAccessible(true);
|
||||||
|
return MethodHandleProxies.asInterfaceInstance(Function.class, MethodHandles.lookup().unreflect(method));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new BusinessException("创建方法引用失败:" + clazz.getName() + StringConstants.DOT + methodName, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -27,13 +27,10 @@ import cn.hutool.core.util.ReflectUtil;
|
|||||||
import cn.hutool.extra.spring.SpringUtil;
|
import cn.hutool.extra.spring.SpringUtil;
|
||||||
import com.mybatisflex.core.paginate.Page;
|
import com.mybatisflex.core.paginate.Page;
|
||||||
import com.mybatisflex.core.query.QueryWrapper;
|
import com.mybatisflex.core.query.QueryWrapper;
|
||||||
import jakarta.el.MethodNotFoundException;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.lang.NonNull;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import top.continew.starter.core.constant.StringConstants;
|
import top.continew.starter.core.constant.StringConstants;
|
||||||
import top.continew.starter.core.exception.BusinessException;
|
|
||||||
import top.continew.starter.core.util.ReflectUtils;
|
import top.continew.starter.core.util.ReflectUtils;
|
||||||
import top.continew.starter.core.util.TreeUtils;
|
import top.continew.starter.core.util.TreeUtils;
|
||||||
import top.continew.starter.core.util.validation.ValidationUtils;
|
import top.continew.starter.core.util.validation.ValidationUtils;
|
||||||
@@ -50,10 +47,7 @@ import top.continew.starter.extension.crud.model.query.SortQuery;
|
|||||||
import top.continew.starter.extension.crud.model.resp.LabelValueResp;
|
import top.continew.starter.extension.crud.model.resp.LabelValueResp;
|
||||||
import top.continew.starter.extension.crud.model.resp.PageResp;
|
import top.continew.starter.extension.crud.model.resp.PageResp;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandleProxies;
|
|
||||||
import java.lang.invoke.MethodHandles;
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
@@ -123,9 +117,10 @@ public class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseIdDO, L, D,
|
|||||||
return TreeUtil.build(list, rootId, treeNodeConfig, (node,
|
return TreeUtil.build(list, rootId, treeNodeConfig, (node,
|
||||||
tree) -> buildTreeField(isSimple, node, tree, treeField));
|
tree) -> buildTreeField(isSimple, node, tree, treeField));
|
||||||
} else {
|
} else {
|
||||||
Function<L, Long> getId = createMethodReference(listClass, CharSequenceUtil.genGetter(treeField.value()));
|
Function<L, Long> getId = ReflectUtils.createMethodReference(listClass, CharSequenceUtil.genGetter(treeField
|
||||||
Function<L, Long> getParentId = createMethodReference(listClass, CharSequenceUtil.genGetter(treeField
|
.value()));
|
||||||
.parentIdKey()));
|
Function<L, Long> getParentId = ReflectUtils.createMethodReference(listClass, CharSequenceUtil
|
||||||
|
.genGetter(treeField.parentIdKey()));
|
||||||
// 构建多根节点树
|
// 构建多根节点树
|
||||||
return TreeUtils.buildMultiRoot(list, getId, getParentId, treeNodeConfig, (node,
|
return TreeUtils.buildMultiRoot(list, getId, getParentId, treeNodeConfig, (node,
|
||||||
tree) -> buildTreeField(isSimple, node, tree, treeField));
|
tree) -> buildTreeField(isSimple, node, tree, treeField));
|
||||||
@@ -155,53 +150,6 @@ public class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseIdDO, L, D,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 通过反射创建方法引用,支持在父类中查找方法
|
|
||||||
*
|
|
||||||
* @param clazz 实体类类型
|
|
||||||
* @param methodName 方法名
|
|
||||||
* @param <T> 实体类类型
|
|
||||||
* @param <K> 返回值类型
|
|
||||||
* @return Function<T, K> 方法引用
|
|
||||||
* @throws IllegalArgumentException 如果参数不合法
|
|
||||||
* @throws MethodNotFoundException 如果在类层次结构中找不到指定方法
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public static <T, K> Function<T, K> createMethodReference(@NonNull Class<T> clazz, @NonNull String methodName) {
|
|
||||||
Method method = getMethod(clazz, methodName);
|
|
||||||
try {
|
|
||||||
// 设置访问权限并返回方法引用
|
|
||||||
method.setAccessible(true);
|
|
||||||
return MethodHandleProxies.asInterfaceInstance(Function.class, MethodHandles.lookup().unreflect(method));
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new BusinessException("创建方法引用失败: " + clazz.getName() + "." + methodName, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取方法(包括父类)
|
|
||||||
*
|
|
||||||
* @param clazz 实体类
|
|
||||||
* @param methodName 方法名
|
|
||||||
* @param <T> 实体类
|
|
||||||
* @return 方法
|
|
||||||
*/
|
|
||||||
private static <T> Method getMethod(Class<T> clazz, String methodName) {
|
|
||||||
Class<?> currentClass = clazz;
|
|
||||||
Method method = null;
|
|
||||||
// 查找方法(包括父类)
|
|
||||||
while (currentClass != null) {
|
|
||||||
try {
|
|
||||||
method = currentClass.getDeclaredMethod(methodName);
|
|
||||||
break;
|
|
||||||
} catch (NoSuchMethodException e) {
|
|
||||||
// 继续查找父类
|
|
||||||
currentClass = currentClass.getSuperclass();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return method;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public D get(Long id) {
|
public D get(Long id) {
|
||||||
T entity = super.getById(id);
|
T entity = super.getById(id);
|
||||||
|
@@ -30,13 +30,10 @@ import cn.hutool.extra.spring.SpringUtil;
|
|||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
import jakarta.el.MethodNotFoundException;
|
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.springframework.data.domain.Sort;
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.lang.NonNull;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import top.continew.starter.core.constant.StringConstants;
|
import top.continew.starter.core.constant.StringConstants;
|
||||||
import top.continew.starter.core.exception.BusinessException;
|
|
||||||
import top.continew.starter.core.util.ClassUtils;
|
import top.continew.starter.core.util.ClassUtils;
|
||||||
import top.continew.starter.core.util.ReflectUtils;
|
import top.continew.starter.core.util.ReflectUtils;
|
||||||
import top.continew.starter.core.util.TreeUtils;
|
import top.continew.starter.core.util.TreeUtils;
|
||||||
@@ -56,10 +53,7 @@ import top.continew.starter.extension.crud.model.query.SortQuery;
|
|||||||
import top.continew.starter.extension.crud.model.resp.LabelValueResp;
|
import top.continew.starter.extension.crud.model.resp.LabelValueResp;
|
||||||
import top.continew.starter.extension.crud.model.resp.PageResp;
|
import top.continew.starter.extension.crud.model.resp.PageResp;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandleProxies;
|
|
||||||
import java.lang.invoke.MethodHandles;
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
@@ -128,9 +122,10 @@ public class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseIdDO, L, D,
|
|||||||
return TreeUtil.build(list, rootId, treeNodeConfig, (node,
|
return TreeUtil.build(list, rootId, treeNodeConfig, (node,
|
||||||
tree) -> buildTreeField(isSimple, node, tree, treeField));
|
tree) -> buildTreeField(isSimple, node, tree, treeField));
|
||||||
} else {
|
} else {
|
||||||
Function<L, Long> getId = createMethodReference(listClass, CharSequenceUtil.genGetter(treeField.value()));
|
Function<L, Long> getId = ReflectUtils.createMethodReference(listClass, CharSequenceUtil.genGetter(treeField
|
||||||
Function<L, Long> getParentId = createMethodReference(listClass, CharSequenceUtil.genGetter(treeField
|
.value()));
|
||||||
.parentIdKey()));
|
Function<L, Long> getParentId = ReflectUtils.createMethodReference(listClass, CharSequenceUtil
|
||||||
|
.genGetter(treeField.parentIdKey()));
|
||||||
// 构建多根节点树
|
// 构建多根节点树
|
||||||
return TreeUtils.buildMultiRoot(list, getId, getParentId, treeNodeConfig, (node,
|
return TreeUtils.buildMultiRoot(list, getId, getParentId, treeNodeConfig, (node,
|
||||||
tree) -> buildTreeField(isSimple, node, tree, treeField));
|
tree) -> buildTreeField(isSimple, node, tree, treeField));
|
||||||
@@ -160,52 +155,6 @@ public class CrudServiceImpl<M extends BaseMapper<T>, T extends BaseIdDO, L, D,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 通过反射创建方法引用,支持在父类中查找方法
|
|
||||||
*
|
|
||||||
* @param clazz 实体类类型
|
|
||||||
* @param methodName 方法名
|
|
||||||
* @param <T> 实体类类型
|
|
||||||
* @param <K> 返回值类型
|
|
||||||
* @return Function<T, K> 方法引用
|
|
||||||
* @throws IllegalArgumentException 如果参数不合法
|
|
||||||
* @throws MethodNotFoundException 如果在类层次结构中找不到指定方法
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public static <T, K> Function<T, K> createMethodReference(@NonNull Class<T> clazz, @NonNull String methodName) {
|
|
||||||
try {
|
|
||||||
Method method = getMethod(clazz, methodName);
|
|
||||||
method.setAccessible(true);
|
|
||||||
return MethodHandleProxies.asInterfaceInstance(Function.class, MethodHandles.lookup().unreflect(method));
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new BusinessException("创建方法引用失败:" + clazz.getName() + StringConstants.DOT + methodName, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取方法(包括父类)
|
|
||||||
*
|
|
||||||
* @param clazz 实体类
|
|
||||||
* @param methodName 方法名
|
|
||||||
* @param <T> 实体类
|
|
||||||
* @return 方法
|
|
||||||
*/
|
|
||||||
private static <T> Method getMethod(Class<T> clazz, String methodName) {
|
|
||||||
Class<?> currentClass = clazz;
|
|
||||||
Method method = null;
|
|
||||||
// 查找方法(包括父类)
|
|
||||||
while (currentClass != null) {
|
|
||||||
try {
|
|
||||||
method = currentClass.getDeclaredMethod(methodName);
|
|
||||||
break;
|
|
||||||
} catch (NoSuchMethodException e) {
|
|
||||||
// 继续查找父类
|
|
||||||
currentClass = currentClass.getSuperclass();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return method;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public D get(Long id) {
|
public D get(Long id) {
|
||||||
T entity = super.getById(id, false);
|
T entity = super.getById(id, false);
|
||||||
|
Reference in New Issue
Block a user