package com.feicent.core.util;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 反射工具类
*/
public class ReflectionUtils {
private static final Logger LOGGER = LoggerFactory.getLogger(ReflectionUtils.class);
/**
* 获取对象的所有属性
* @param object
* @return
*/
public static List<Field> getAllFields(Object object) {
List<Field> fieldList = new ArrayList<>();
Class clazz = object.getClass();
// 当父类为null的时候说明到达了最上层的父类(Object类).
while (clazz != null) {
fieldList.addAll(Arrays.asList(clazz.getDeclaredFields()));
// 得到父类,然后赋给自己
clazz = clazz.getSuperclass();
}
return fieldList;
}
/**
* 直接调用对象方法, 无视private/protected修饰符
* 只匹配函数名,如果有多个同名函数调用第一个
*/
public static Object invokeMethodByName(final Object obj, final String methodName, final Object[] args) {
try {
Method method = getAccessibleMethodByName(obj, methodName);
return method.invoke(obj, args);
} catch (Exception e) {
LOGGER.error("error.invokeMethodByName", e);
}
}
/**
* 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
* 如向上转型到Object仍无法找到, 返回null.
* 只匹配函数名。
*
* 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
*/
public static Method getAccessibleMethodByName(final Object obj, final String methodName) {
Validate.notNull(obj, "object can't be null");
Validate.notBlank(methodName, "methodName can't be blank");
for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
Method[] methods = searchType.getDeclaredMethods();
for (Method method : methods) {
if (method.getName().equals(methodName)) {
makeAccessible(method);
return method;
}
}
}
return null;
}
/**
* 改变private/protected的成员变量为public
*/
public static void makeAccessible(Field field) {
if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())
|| Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) {
field.setAccessible(true);
}
}
/**
* 改变private/protected的方法为public
*/
public static void makeAccessible(Method method) {
if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
&& !method.isAccessible()) {
method.setAccessible(true);
}
}
}