com.gitee.apanlh.util.reflection.ReflectionUtils Maven / Gradle / Ivy
package com.gitee.apanlh.util.reflection;
import com.gitee.apanlh.exp.InstanceException;
import com.gitee.apanlh.util.base.CollUtils;
import com.gitee.apanlh.util.base.Empty;
import com.gitee.apanlh.util.base.IteratorUtils;
import com.gitee.apanlh.util.base.MapUtils;
import com.gitee.apanlh.util.base.StringUtils;
import com.gitee.apanlh.util.cache.local.Cache;
import com.gitee.apanlh.util.cache.local.CacheUtils;
import com.gitee.apanlh.util.valid.Assert;
import com.gitee.apanlh.util.valid.ValidParam;
import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;
/**
* 反射工具类
*
* @author Pan
*/
public class ReflectionUtils {
/** 构造器缓存 */
static final Cache, Constructor>[]> CONSTRUCTORS_CACHE = CacheUtils.cache(256);
/** 方法缓存 */
static final Cache, Method[]> METHODS_CACHE = CacheUtils.cache(256);
/** 字段缓存 */
static final FieldProvider FIELD_PROVIDER = new FieldCache();
/**
* 构造函数
*
* @author Pan
*/
private ReflectionUtils() {
// 不允许外部实例
super();
}
/**
* 扫描类是否同时存在某注解
*
如果其中一个不存在则返回false
*
与条件
*
* @author Pan
* @param clazz 类
* @param annotations 注解
* @return boolean
*/
@SafeVarargs
public static boolean scanClassAnnotation(Class> clazz, Class extends Annotation>... annotations) {
return scanAnnotationAnd(clazz, null, annotations);
}
/**
* 扫描类中字段是否存在某注解
*
存在返回对应注解的{@code List}
*
true为存在
*
* @author Pan
* @param 数据类型
* @param field 字段对象
* @param annotation 注解
* @return boolean
*/
public static boolean scanFieldAnnotation(Field field, Class annotation) {
return ValidParam.isNotNull(getFieldAnnotation(field, annotation));
}
/**
* 扫描类中字段是否存在某注解
*
多个注解时为(与条件)判断
*
true为存在
*
* @author Pan
* @param clazz 类
* @param annotations 注解
* @return boolean
*/
@SafeVarargs
public static boolean scanFieldAnnotation(Class> clazz, Class extends Annotation>... annotations) {
Field[] fields = getFields(clazz);
for (int i = 0, len = fields.length; i < len; i++) {
Field field = fields[i];
if (scanAnnotationAnd(null, field, annotations)) {
return true;
}
}
return false;
}
/**
* 扫描注解
*
与条件
*
* @author Pan
* @param 数据类型
* @param clazz 类
* @param accessibleObject 方法、字段对象
* @param annotations 注解
* @return boolean
*/
@SafeVarargs
public static boolean scanAnnotationAnd(Class> clazz, T accessibleObject, Class extends Annotation>... annotations) {
if (clazz == null) {
for (Class extends Annotation> annotation : annotations) {
if (!accessibleObject.isAnnotationPresent(annotation)) {
return false;
}
}
} else {
// 类
for (Class extends Annotation> annotation : annotations) {
if (!clazz.isAnnotationPresent(annotation)) {
return false;
}
}
}
return true;
}
/**
* 扫描注解
*
或条件
*
* @author Pan
* @param 数据类型
* @param clazz 类
* @param accessibleObject 方法、字段对象
* @param annotations 注解
* @return boolean
*/
@SafeVarargs
public static boolean scanAnnotationOr(Class> clazz, T accessibleObject, Class extends Annotation>... annotations) {
if (clazz == null) {
for (Class extends Annotation> annotation : annotations) {
if (accessibleObject.isAnnotationPresent(annotation)) {
return true;
}
}
} else {
// 类
for (Class extends Annotation> annotation : annotations) {
if (clazz.isAnnotationPresent(annotation)) {
return true;
}
}
}
return false;
}
/**
* 获取该类下的所有构造函数
*
* @author Pan
* @param clazz 类
* @return Constructor[]
*/
private static Constructor>[] getDeclaredConstructors(Class> clazz) {
return clazz.getDeclaredConstructors();
}
/**
* 获取该类下所有构造函数
*
* @author Pan
* @param clazz 类
* @return Constructor[]
*/
public static Constructor>[] getConstructors(Class> clazz) {
Constructor>[] constructors = CONSTRUCTORS_CACHE.get(clazz);
// 获取该类所有构造
return constructors == null ? CONSTRUCTORS_CACHE.put(clazz, getDeclaredConstructors(clazz)) : constructors;
}
/**
* 获取构造函数
*
* @author Pan
* @param 数据类型
* @param clazz 类
* @param callTypes 构造参数类型
* @return Constructor
*/
@SuppressWarnings("unchecked")
public static Constructor getConstructor(Class clazz, Class>... callTypes) {
Constructor>[] constructors = CONSTRUCTORS_CACHE.get(clazz);
// 缓存不存在获取将获取该类所有构造函数
if (constructors == null) {
constructors = getConstructors(clazz);
}
// 因为存在基本类型与包装类 类型问题 所以需要对比正确调用构造函数
for (int i = 0, len = constructors.length; i < len; i++) {
Constructor> constructor = constructors[i];
// 获取正确构造函数
if (compareParamType(constructor.getParameterTypes(), callTypes)) {
// 开启权限
setAccessible(constructor);
return (Constructor) constructor;
}
}
return null;
}
/**
* 获取该类下所有方法
*
* @author Pan
* @param clazz 类
* @return Method[]
*/
private static Method[] getDeclaredMethods(Class> clazz) {
return clazz.getDeclaredMethods();
}
/**
* 获取该类下的某个方法
*
* @author Pan
* @param clazz 类
* @param methodName 方法名
* @return Method
*/
public static Method getMethod(Class> clazz, String methodName) {
Assert.isNotEmpty(methodName);
Method[] methods = getMethods(clazz);
for (int i = 0, len = methods.length; i < len; i++) {
Method method = methods[i];
if (StringUtils.eq(method.getName(), methodName)) {
return method;
}
}
return null;
}
/**
* 获取该类下的所有方法
*
* @author Pan
* @param clazz 类
* @return Method[]
*/
public static Method[] getMethods(Class> clazz) {
Method[] methods = METHODS_CACHE.get(clazz);
return methods == null ? METHODS_CACHE.put(clazz, getDeclaredMethods(clazz)): methods;
}
/**
* 根据字段名返回Field
*
* @author Pan
* @param 数据类型
* @param obj 对象
* @param searchNames 字段名
* @return Field
*/
public static Field getField(T obj, String searchNames) {
if (obj == null) {
return null;
}
return FIELD_PROVIDER.getField(obj.getClass(), searchNames);
}
/**
* 根据字段名返回Field
*
* @author Pan
* @param clazz 类
* @param searchNames 字段名
* @return Field
*/
public static Field getField(Class> clazz, String searchNames) {
return FIELD_PROVIDER.getField(clazz, searchNames);
}
/**
* 获取该类下的所有字段
*
默认获取静态字段
*
* @author Pan
* @param 数据类型
* @param t 对象
* @return Field[]
*/
public static Field[] getFields(T t) {
return FIELD_PROVIDER.getFields(t);
}
/**
* 获取该类下的字段
*
自定义是否忽略静态字段
*
* @author Pan
* @param 数据类型
* @param t 对象
* @param ignoreStaticField true忽略静态字段
* @return Field[]
*/
public static Field[] getFields(T t, boolean ignoreStaticField) {
return FIELD_PROVIDER.getFields(t, ignoreStaticField);
}
/**
* 获取该类下的字段
*
自定义反射缓存
*
* @author Pan
* @param 数据类型
* @param t 对象
* @param fieldCacheObject 反射缓存
* @return Field[]
*/
public static Field[] getFields(T t, FieldCacheObject fieldCacheObject) {
return FIELD_PROVIDER.getFields(t, fieldCacheObject);
}
/**
* 获取该类下的所有字段
*
返回该集合首个元素的所有字段对象
*
默认忽略静态字段
*
* @author Pan
* @param 数据类型
* @param list 集合
* @return Field[]
*/
public static Field[] getFields(List list) {
return FIELD_PROVIDER.getFields(list);
}
/**
* 获取该类下的字段
*
自定义是否忽略静态字段
*
* @author Pan
* @param 数据类型
* @param list 集合
* @param ignoreStaticField true忽略静态字段
* @return Field[]
*/
public static Field[] getFields(List list, boolean ignoreStaticField) {
return FIELD_PROVIDER.getFields(list, ignoreStaticField);
}
/**
* 获取该类下的字段
*
自定义反射配置
*
* @author Pan
* @param 数据类型
* @param list 集合
* @param fieldCacheObject 反射缓存
* @return Field[]
*/
public static Field[] getFields(List list, FieldCacheObject fieldCacheObject) {
return FIELD_PROVIDER.getFields(list, fieldCacheObject);
}
/**
* 获取该类下的所有字段
*
默认忽略静态字段
*
* @author Pan
* @param clazz 类
* @return Field[]
*/
public static Field[] getFields(Class> clazz) {
return FIELD_PROVIDER.getFields(clazz);
}
/**
* 获取该类下的字段
*
自定义是否忽略静态字段
*
* @author Pan
* @param clazz 类
* @param ignoreStaticField true忽略静态字段
* @return Field[]
*/
public static Field[] getFields(Class> clazz, boolean ignoreStaticField) {
return FIELD_PROVIDER.getFields(clazz, ignoreStaticField);
}
/**
* 获取该类下的字段
*
自定义反射配置
*
自定义忽略对象
*
* @author Pan
* @param clazz 类
* @param fieldCacheObject 反射缓存
* @return Field[]
*/
public static Field[] getFields(Class> clazz, FieldCacheObject fieldCacheObject) {
return FIELD_PROVIDER.getFields(clazz, fieldCacheObject);
}
/**
* 如果搜索到相对应的name值
*
返回所需要的Field[]
*
已开启访问控制权限
*
* @author Pan
* @param clazz 类
* @param searchKeys 搜索值
* @return List
*/
public static List getFields(Class> clazz, String... searchKeys) {
if (ValidParam.isEmpty(searchKeys)) {
return Empty.list();
}
Field[] fields = getFields(clazz);
return CollUtils.newArrayList(thisList ->
// 先搜索searchKeys参数保证传递值为有序
IteratorUtils.array(searchKeys, key ->
IteratorUtils.array(fields, field -> {
if (StringUtils.eq(field.getName(), key)) {
thisList.add(field);
}
})
)
);
}
/**
* 获取Field转化为Map格式
*
*
Key = 字段名
*
Value = Field对象
*
* @author Pan
* @param 数据类型
* @param obj 对象
* @return Map
*/
public static Map getFieldsToMap(T obj) {
return getFieldsToMap(obj.getClass());
}
/**
* 获取Field转化为Map格式
*
*
Key = 字段名
*
Value = Field对象
*
* @author Pan
* @param clazz 类
* @return Map
*/
public static Map getFieldsToMap(Class> clazz) {
Field[] fields = getFields(clazz);
return MapUtils.newHashMap(map -> IteratorUtils.array(fields, field -> map.put(field.getName(), field)), fields.length);
}
/**
* 根据字段对象获取当前值
*
开启访问权限
*
* @author Pan
* @param 数据类型
* @param field 字段
* @param obj 对象
* @return Object
*/
public static Object getFieldValue(Field field, T obj) {
try {
setAccessible(field);
return field.get(obj);
} catch (Exception e) {
throw new IllegalArgumentException(StringUtils.format("get field value error cause:{}", e.getMessage()), e);
}
}
/**
* 根据字段名获取对应的值
*
开启访问权限
*
* @author Pan
* @param 数据类型
* @param obj 对象
* @param fieldName 字段名
* @return Object
*/
public static Object getFieldValue(T obj, String fieldName) {
Assert.isNotEmpty(fieldName);
Field field = getField(obj, fieldName);
if (field == null) {
return null;
}
return getFieldValue(field, obj);
}
/**
* 根据字段名获取对应的值
*
开启访问权限
*
* @author Pan
* @param 真实数据类型
* @param 返回类型
* @param obj 传递对象
* @param fieldName 字段名
* @param clazz 指定class
* @return T
*/
@SuppressWarnings("unchecked")
public static R getFieldValue(T obj, String fieldName, Class clazz) {
Assert.isNotEmpty(fieldName);
if (obj == null) {
return null;
}
Field field = getField(obj.getClass(), fieldName);
if (field == null) {
return null;
}
return (R) getFieldValue(field, obj);
}
/**
* 搜索集合对象中的某个字段返回
*
* @author Pan
* @param 数据类型
* @param list 集合
* @param fieldName 搜索字段
* @return List
*/
public static List