导包
<!-- 谷歌公共依赖核心库 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>20.0</version>
</dependency>
工具类
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Date;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.poi.ss.usermodel.DateUtil;
import com.google.common.reflect.Reflection;
/**
* 反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 动态代理
*
* @author ycs
*/
@SuppressWarnings("rawtypes")
public class YcsReflectUtils {
private static final String SETTER_PREFIX = "set";
private static final String GETTER_PREFIX = "get";
/**
* 调用Getter方法.
* 支持多级,如:对象名.对象名.方法
*/
@SuppressWarnings("unchecked")
public static <E> E invokeGetter(Object obj, String propertyName) {
Object object = obj;
for (String name : StringUtils.split(propertyName, ".")) {
String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);
object = invokeMethod(object, getterMethodName, new Class[]{}, new Object[]{});
}
return (E) object;
}
/**
* 调用Setter方法, 仅匹配方法名。
* 支持多级,如:对象名.对象名.方法
*/
public static <E> void invokeSetter(Object obj, String propertyName, E value) {
Object object = obj;
String[] names = StringUtils.split(propertyName, ".");
for (int i = 0; i < names.length; i++) {
if (i < names.length - 1) {
String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);
object = invokeMethod(object, getterMethodName, new Class[]{}, new Object[]{});
} else {
String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);
invokeMethod(object, setterMethodName, new Object[]{value});
}
}
}
/**
* 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数.
*/
@SuppressWarnings("unchecked")
public static <E> E getFieldValue(final Object obj, final String fieldName) {
Field field = getAccessibleField(obj, fieldName);
if (field == null) {
throw new RuntimeException("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 ");
}
E result = null;
try {
result = (E) field.get(obj);
} catch (IllegalAccessException e) {
throw new RuntimeException("调用get方法失败!" + e);
}
return result;
}
/**
* 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数.
*/
public static <E> void setFieldValue(final Object obj, final String fieldName, final E value) {
Field field = getAccessibleField(obj, fieldName);
if (field == null) {
// throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 ");
throw new RuntimeException("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 ");
}
try {
field.set(obj, value);
} catch (IllegalAccessException e) {
throw new RuntimeException("调用set方法失败!" + e);
}
}
/**
* 直接调用对象方法, 无视private/protected修饰符.
* 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用.
* 同时匹配方法名+参数类型,
*/
@SuppressWarnings("unchecked")
public static <E> E invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,
final Object[] args) {
if (obj == null || methodName == null) {
return null;
}
Method method = getAccessibleMethod(obj, methodName, parameterTypes);
if (method == null) {
throw new RuntimeException("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 ");
}
try {
return (E) method.invoke(obj, args);
} catch (Exception e) {
String msg = "method: " + method + ", obj: " + obj + ", args: " + Arrays.toString(args) + "\n";
throw new RuntimeException(msg, e);
}
}
/**
* 直接调用对象方法, 无视private/protected修饰符,
* 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用.
* 只匹配函数名,如果有多个同名函数调用第一个。
*/
@SuppressWarnings("unchecked")
public static <E> E invokeMethod(final Object obj, final String methodName, final Object[] args) {
Method method = getAccessibleMethodByName(obj, methodName, args.length);
if (method == null) {
throw new RuntimeException("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 ");
}
try {
// 类型转换(将参数数据类型转换为目标方法参数类型)
Class<?>[] cs = method.getParameterTypes();
for (int i = 0; i < cs.length; i++) {
if (args[i] != null && !args[i].getClass().equals(cs[i])) {
if (cs[i] == String.class) {
args[i] = YcsConvertUtils.toStr(args[i]);
if (StringUtils.endsWith((String) args[i], ".0")) {
args[i] = StringUtils.substringBefore((String) args[i], ".0");
}
} else if (cs[i] == Integer.class) {
args[i] = YcsConvertUtils.toInt(args[i]);
} else if (cs[i] == Long.class) {
args[i] = YcsConvertUtils.toLong(args[i]);
} else if (cs[i] == Double.class) {
args[i] = YcsConvertUtils.toDouble(args[i]);
} else if (cs[i] == Float.class) {
args[i] = YcsConvertUtils.toFloat(args[i]);
} else if (cs[i] == Date.class) {
if (args[i] instanceof String) {
args[i] = YcsDateUtils.parseDate((String) args[i]);
} else {
args[i] = DateUtil.getJavaDate((Double) args[i]);
}
} else if (cs[i] == boolean.class || cs[i] == Boolean.class) {
args[i] = YcsConvertUtils.toBool(args[i]);
}
}
}
return (E) method.invoke(obj, args);
} catch (Exception e) {
String msg = "method: " + method + ", obj: " + obj + ", args: " + Arrays.toString(args) + "\n";
throw new RuntimeException(msg, e);
}
}
/**
* 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问.
* <p>
* 如向上转型到Object仍无法找到, 返回null.
*
* @param obj
* @param fieldName
* @return
*/
private static Field getAccessibleField(final Object obj, final String fieldName) {
// 为空不报错。直接返回 null
if (obj == null) {
return null;
}
Validate.notBlank(fieldName, "fieldName can't be blank");
for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
try {
Field field = superClass.getDeclaredField(fieldName);
makeAccessible(field);
return field;
} catch (NoSuchFieldException e) {
continue;
}
}
return null;
}
/**
* 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
* <p>
* 如向上转型到Object仍无法找到, 返回null.
* <p>
* 匹配函数名+参数类型。
* <p>
* 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
*
* @param obj
* @param methodName
* @param parameterTypes
* @return
*/
private static Method getAccessibleMethod(final Object obj, final String methodName,
final Class<?>... parameterTypes) {
// 为空不报错。直接返回 null
if (obj == null) {
return null;
}
Validate.notBlank(methodName, "methodName can't be blank");
for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
try {
Method method = searchType.getDeclaredMethod(methodName, parameterTypes);
makeAccessible(method);
return method;
} catch (NoSuchMethodException e) {
continue;
}
}
return null;
}
/**
* 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
* <p>
* 如向上转型到Object仍无法找到, 返回null.
* <p>
* 只匹配函数名。
* <p>
* 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
*
* @param obj
* @param methodName
* @param argsNum
* @return
*/
private static Method getAccessibleMethodByName(final Object obj, final String methodName, int argsNum) {
// 为空不报错。直接返回 null
if (obj == null) {
return 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) && method.getParameterTypes().length == argsNum) {
makeAccessible(method);
return method;
}
}
}
return null;
}
/**
* 改变private/protected的方法为public
*
* @param method
*/
private static void makeAccessible(Method method) {
if ((!Modifier.isPublic(method.getModifiers())
|| !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
&& !method.isAccessible()) {
method.setAccessible(true);
}
}
/**
* 改变private/protected的成员变量为public
*
* @param field
*/
private static void makeAccessible(Field field) {
if ((!Modifier.isPublic(field.getModifiers())
|| !Modifier.isPublic(field.getDeclaringClass().getModifiers())
|| Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) {
field.setAccessible(true);
}
}
/**
* 动态代理
*
* @param interfaceType 接口
* @param handler 处理器
* @param <T>
* @return
*/
public static <T> T getProxy(Class<T> interfaceType, InvocationHandler handler) {
return Reflection.newProxy(interfaceType, handler);
}
}
测试
/**
* @author ycs
*/
public class SelfTest {
private File desktopDir;
/**
* 系统桌面路径
*/
private String desktopPath;
@Before
public void desktopDirTest() {
desktopDir = FileSystemView.getFileSystemView().getHomeDirectory();
desktopPath = desktopDir.getAbsolutePath();
}
@Test
public void ReflectUtils() {
ChannelInit init = new ChannelInit();
YcsReflectUtils.invokeSetter(init, "itemIds", Lists.newArrayList(1, 2, 3));
List<Long> itemIds = YcsReflectUtils.invokeGetter(init, "itemIds");
YcsReflectUtils.setFieldValue(init, "attrName", "attr");
String attr = YcsReflectUtils.getFieldValue(init, "attrName");
YcsReflectUtils.invokeMethod(init, "test", new Object[]{});
System.out.println(init);
InSercie foo = YcsReflectUtils.getProxy(InSercie.class, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("proxy");
return method.invoke(init, args);
}
});
foo.test();
}
}
版权声明:本文为weixin_44215249原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。