All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.gitee.apanlh.util.reflection.ReflectionUtils Maven / Gradle / Ivy

There is a newer version: 2.0.0.2
Show newest version
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... 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... 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... annotations) { if (clazz == null) { for (Class annotation : annotations) { if (!accessibleObject.isAnnotationPresent(annotation)) { return false; } } } else { // 类 for (Class 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... annotations) { if (clazz == null) { for (Class annotation : annotations) { if (accessibleObject.isAnnotationPresent(annotation)) { return true; } } } else { // 类 for (Class 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 getFieldValue(List list, String fieldName) { return getFieldValue(list, fieldName, Object.class); } /** * 搜索集合对象中的某个字段返回 *
返回指定类型 * * @author Pan * @param 数据类型 * @param 返回类型 * @param list 集合 * @param fieldName 搜索字段 * @param clazz 类 * @return List */ @SuppressWarnings("unchecked") public static List getFieldValue(List list, String fieldName, Class clazz) { Assert.isNotEmpty(fieldName); if (ValidParam.isEmpty(list)) { return Empty.list(); } Field field = FIELD_PROVIDER.getField(ClassUtils.getClass(list), fieldName); if (field == null) { return Empty.list(); } return CollUtils.newArrayList(newList -> IteratorUtils.array(list, t -> newList.add((R) getFieldValue(field, t))), list.size()); } /** * 有序返回该类所有字段属性值 * * @author Pan * @param 真实数据类型 * @param bean 对象 * @return List */ public static List getFieldsValue(T bean) { Field[] fields = getFields(bean); return CollUtils.newArrayList(list -> IteratorUtils.array(fields, field -> list.add(getFieldValue(field, bean))), fields.length); } /** * 返回该类所有字段属性值 *
key=字段名,value=值 *
无序返回 * * @author Pan * @param 真实数据类型 * @param bean 对象 * @return Map */ public static Map getFieldsValueToMap(T bean) { Field[] fields = getFields(bean); return MapUtils.newHashMap(map -> IteratorUtils.array(fields, field -> map.put(field.getName(), getFieldValue(field, bean))), fields.length); } /** * 返回该类所有字段属性值 *
key=字段名,value=值 *
有序返回 * * @author Pan * @param 真实数据类型 * @param bean 对象 * @return Map */ public static Map getFieldsValueToLinkedHashMap(T bean) { Field[] fields = getFields(bean); return MapUtils.newLinkedHashMap(map -> IteratorUtils.array(fields, field -> map.put(field.getName(), getFieldValue(field, bean))), fields.length); } /** * 设置该类下某个字段的值 * * @author Pan * @param 数据类型 * @param 返回类型 * @param obj 对象 * @param fieldName 字段名 * @param value 值 * @return V */ public static V setFieldValue(T obj, String fieldName, V value) { if (obj == null || value == null) { return null; } Field field = getField(obj.getClass(), fieldName); if (field == null) { return null; } return setFieldValue(field, obj, value); } /** * 设置Field字段值 * * @author Pan * @param 数据类型 * @param 返回类型 * @param field 字段名 * @param obj 对象 * @param value 值 * @return V */ public static V setFieldValue(Field field, T obj, V value) { if (field == null || obj == null || value == null) { return null; } if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) || Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) { setAccessible(field); } try { field.set(obj, value); return value; } catch (Exception e) { throw new IllegalArgumentException(StringUtils.format("set field value error cause:{}", e.getMessage()), e); } } /** * 修改static final字段值 * * @author Pan * @param field 字段 * @param newValue 值 */ public static void setFieldStaticFinal(Field field, Object newValue) { try { Field modifiersField = Field.class.getDeclaredField("modifiers"); setAccessible(field); setAccessible(modifiersField); modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); field.set(null, newValue); } catch (Exception e) { throw new IllegalArgumentException(e.getMessage(), e); } } /** * Map设置该类下某个一个或多个字段的值 * * @author Pan * @param 返回类型 * @param 值类型 * @param clazz 类 * @param params 参数 * @return T */ public static T setFields(Class clazz, Map params) { T newInstance = newInstance(clazz); setFields(newInstance, params); return newInstance; } /** * Map设置该类下某个一个或多个字段的值 * * @author Pan * @param 数据类型 * @param 值类型 * @param obj 对象 * @param params 参数 */ public static void setFields(T obj, Map params) { if (MapUtils.isEmpty(params)) { return ; } Field[] fields = getFields(obj); // 设置值 IteratorUtils.array(fields, field -> setFieldValue(field, obj, params.get(field.getName()))); } /** * 扫描类是否存在注解 如果存在返回注解值 * * @author Pan * @param 数据类型 * @param clazz 类 * @param annotation 注解 * @return Annotation */ public static Annotation getClassAnnotation(Class clazz, Class annotation) { Annotation[] declaredAnnotations = clazz.getDeclaredAnnotations(); for (int i = 0, len = declaredAnnotations.length; i < len; i++) { Annotation declaredAnnotation = declaredAnnotations[i]; if (declaredAnnotation.annotationType().equals(annotation)) { return declaredAnnotation; } } return null; } /** * 扫描类中方法是否存在某注解 *
存在返回对应注解的{@code List} *
多个注解时为(与条件)判断 * * @author Pan * @param clazz 类 * @param annotations 注解 * @return List */ @SafeVarargs public static List getMethodAnnotation(Class clazz, Class... annotations) { Method[] methods = getMethods(clazz); List list = null; for (int i = 0, len = methods.length; i < len; i++) { Method method = methods[i]; if (!scanAnnotationAnd(null, method, annotations)) { continue; } if (list == null) { list = CollUtils.newArrayList(len); } list.add(method); } return list; } /** * 扫描类中字段是否存在某注解 *
存在返回对应注解的{@code List} * * @author Pan * @param clazz 类 * @param annotations 注解 * @return List */ @SafeVarargs public static List getFieldAnnotation(Class clazz, Class... annotations) { Field[] fields = getFields(clazz); List list = CollUtils.newArrayList(); for (int i = 0; i< annotations.length; i++) { Class annotation = annotations[i]; for (int j = 0, len = fields.length; j < len; j++) { Field field = fields[j]; if (getFieldAnnotation(field, annotation) != null) { list.add(field); break; } } } return list; } /** * 扫描类中字段是否存在某注解 *
存在返回对应注解的{@code List} *
多个注解时为(与条件)判断 *
true为存在 * * @author Pan * @param
数据类型 * @param field 字段对象 * @param annotation 注解 * @return Annotation */ public static Annotation getFieldAnnotation(Field field, Class annotation) { Annotation[] annotations = field.getAnnotations(); for (int i = 0, len = annotations.length; i < len; i++) { Annotation declaredAnnotation = annotations[i]; if (declaredAnnotation.annotationType().equals(annotation)) { return declaredAnnotation; } } return null; } /** * 扫描类中字段是否存在某注解 *
存在返回对应注解的{@code List} *
获取对应注解多条件 * * @author Pan * @param clazz 类 * @param annotations 注解 * @return List */ @SafeVarargs public static Field getFieldAnnotationAnd(Class clazz, Class... 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 field; } } return null; } /** * 扫描注解 *
或条件 * * @author Pan * @param 数据类型 * @param clazz 类 * @param accessibleObject 方法、字段对象 * @param annotations 注解 * @return Annotation */ @SafeVarargs public static Annotation getAnnotationValueOr(Class clazz, T accessibleObject, Class... annotations) { if (clazz == null) { for (Class annotation : annotations) { if (accessibleObject.isAnnotationPresent(annotation)) { return accessibleObject.getDeclaredAnnotation(annotation); } } } else { // 类 for (Class annotation : annotations) { if (clazz.isAnnotationPresent(annotation)) { return accessibleObject.getDeclaredAnnotation(annotation); } } } return null; } /** * 构造函数 *
方法 *
字段 *
通用开启权限 * * @author Pan * @param 数据类型 * @param accessibleObject 对象 */ public static void setAccessible(T accessibleObject) { if (accessibleObject == null || accessibleObject.isAccessible()) { return ; } accessibleObject.setAccessible(true); } /** * 对比参数类型 *
原始参数类型与传递参数类型进行对比是否一致 *
避免原始类与包装类不同 *
用于对比构造函数参数类型与传递参数类型是否一致、invoke方法参数对比等 * * @author Pan * @param sourceTypes 原始参数类型 * @param callTypes 调用参数类型 * @return boolean */ public static boolean compareParamType(Class[] sourceTypes, Class[] callTypes) { // 如果都为空则默认为 空构造函数 if (ValidParam.isEmpty(sourceTypes) && ValidParam.isEmpty(callTypes)) { return true; } // 避免之后触发NullPointer if ((sourceTypes == null || callTypes == null) // 如果参数长度不一致跳过 || (sourceTypes.length != callTypes.length)) { return false; } // 对比类型 for (int i = 0, len = sourceTypes.length; i < len; i++) { Class sourceParam = sourceTypes[i]; Class callParam = callTypes[i]; // 首次先对比类型是否一致 if (ClassTypeUtils.isAssignableFrom(sourceParam, callParam)) { return true; } // 如果反射的形参为包装类, 但是这里强转成基本类型了, 方法(method)级采用此类方法可能抛出NosuchMethod异常 // 验证是否是包装类或者原始类 if (!ClassTypeUtils.isBasicDataType(sourceParam) || !ClassTypeUtils.isBasicDataType(callParam)) { return false; } Class convertBasicType = ClassTypeUtils.convertBasicType(sourceParam); Class convertBasicType2 = ClassTypeUtils.convertBasicType(callParam); // 判定此 Class 对象所表示的类或接口与指定的 Class // 参数所表示的类或接口是否相同,或是否是其超类或超接口。如果是则返回 true;否则返回 false。 // 如果该 Class 表示一个基本类型,且指定的 Class 参数正是该 Class 对象,则该方法返回 true;否则返回 false。 // 验证基本类型是否一致 if (!ClassTypeUtils.isAssignableFrom(convertBasicType, convertBasicType2)) { return false; } } return true; } /** * 验证是否是静态方法修饰 * * @author Pan * @param clazz 类 * @param methodName 方法名 * @return boolean */ public static boolean isStaticMethod(Class clazz, String methodName) { Assert.isNotEmpty(methodName); Method method = getMethod(clazz, methodName); if (method == null) { return false; } return Modifier.isStatic(method.getModifiers()); } /** * 是否字段为静态变量 * * @author Pan * @param field 字段对象 * @return boolean */ public static boolean isStaticField(Field field) { return Modifier.isStatic(field.getModifiers()); } /** * 是否是序列化ID * * @author Pan * @param field 字段对象 * @return boolean */ public static boolean isSerialId(Field field) { return StringUtils.eq("serialVersionUID", field.getName()); } /** * 反射调用方法 *

* * 无参方法 *
{@code invoke(MethodInvokeBuilder.builder(Abc.class, "abc")) } *
* *

* 有参方法 *
* {@code invoke(MethodInvokeBuilder.builder(Abc.class, "abc")} *
{@code .setCallParams(1)} *
{@code .setParamType(int.class))} * * @author Pan * @param methodInvokeBuilder 封装调用对象 * @return Object */ public static Object invoke(MethodInvokeBuilder methodInvokeBuilder) { Assert.isNotNull(methodInvokeBuilder); return methodInvokeBuilder.build(); } /** * 实例对象 * * @author Pan * @param 数据类型 * @param clazz 类 * @param params 构造函数参数 * @return T */ public static T newInstance(Class clazz, Object... params) { try { if (params == null || params.length == 0) { return clazz.newInstance(); } // 获取有参构造函数 Class[] classes = ClassUtils.getClasses(params); Constructor constructor = getConstructor(clazz, classes); if (constructor == null) { throw new InstanceException("not found constructor"); } return constructor.newInstance(params); } catch (Exception e) { throw new InstanceException(StringUtils.format("instance error class{} cause:{}", clazz, e.getMessage(), e)); } } }