#525 加强Utils Modules模块:自家的Reflections更新

This commit is contained in:
calvin1978
2017-01-03 14:49:07 +08:00
parent 3caf428cac
commit 22f59fdcf9
4 changed files with 111 additions and 32 deletions
+4 -4
View File
@@ -31,7 +31,7 @@
<version>0.9.10</version>
</dependency>
<!-- for Encodes.java -->
<!-- for Encodes -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
@@ -39,7 +39,7 @@
<optional>true</optional>
</dependency>
<!-- for CollectionExtractor.java -->
<!-- for CollectionExtractor -->
<dependency>
<groupId>commons-beanutils</groupId>
<artifactId>commons-beanutils</artifactId>
@@ -47,7 +47,7 @@
<optional>true</optional>
</dependency>
<!-- for JsonMapper -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
@@ -55,7 +55,7 @@
<optional>true</optional>
</dependency>
<!-- for ObjectMapper -->
<dependency>
<groupId>ma.glasnost.orika</groupId>
<artifactId>orika-core</artifactId>
@@ -9,7 +9,7 @@ package org.springside.modules.utils.base;
*
* @author calvin
*/
public class PropertiesUtil {
public class SystemProperties {
/////////// Boolean.readBoolean()扩展 ///////////////
@@ -10,19 +10,27 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.ClassUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.annotations.Beta;
/**
* 反射工具类.
*
* 提供调用getter/setter方法, 访问私有变量, 调用私有方法.
* 所有反射均无视modifier的范围限制,同时将反射的Checked异常转为UnChecked异常。
*
* 基于这两点要求,没有现有库满足,只能自写
*
* 1. 属性访问:a.调用getter/setter方法, b.直接访问变量, c.直接先尝试查找getter/setter,如果不存在则直接访问变量
*
* 2. 一次性调用方法,其中一个特色函数是invokeByName,不准确匹配参数类型,只取第一个名称符合的函数.
*
* 3. 多次调用方法,先用getAccessibleMethod()获得Method对象,然后多次调用Method对象
*/
@Beta
@SuppressWarnings("unchecked")
public class Reflections {
private static final String SETTER_PREFIX = "set";
@@ -30,26 +38,27 @@ public class Reflections {
private static Logger logger = LoggerFactory.getLogger(Reflections.class);
/////////// 属性相关函数///////////
/**
* 调用Getter方法.
* 调用Getter方法,无视private/protected修饰符.
*/
public static Object invokeGetter(Object obj, String propertyName) {
public static <T> T invokeGetter(Object obj, String propertyName) {
String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(propertyName);
return invokeMethod(obj, getterMethodName, new Class[] {}, new Object[] {});
return (T) invokeMethod(obj, getterMethodName);
}
/**
* 调用Setter方法, 仅匹配方法名。
* 调用Setter方法, 无视private/protected修饰符, 按传入value的类型匹配函数.
*/
public static void invokeSetter(Object obj, String propertyName, Object value) {
String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(propertyName);
invokeMethodByName(obj, setterMethodName, new Object[] { value });
invokeMethod(obj, setterMethodName, new Object[] { value });
}
/**
* 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数.
*/
public static Object getFieldValue(final Object obj, final String fieldName) {
public static <T> T getFieldValue(final Object obj, final String fieldName) {
Field field = getAccessibleField(obj, fieldName);
if (field == null) {
@@ -62,7 +71,7 @@ public class Reflections {
} catch (IllegalAccessException e) {
logger.error("不可能抛出的异常{}", e.getMessage());
}
return result;
return (T) result;
}
/**
@@ -83,10 +92,63 @@ public class Reflections {
}
/**
* 直接调用对象方法, 无视private/protected修饰符. 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用. 同时匹配方法名+参数类型,
* 先尝试用Getter函数读取, 如果不存在则直接读取变量.
*/
public static Object invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,
final Object[] args) {
public static <T> T getProperty(Object obj, String propertyName) {
String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(propertyName);
Method method = getAccessibleMethod(obj, getterMethodName);
if (method != null) {
try {
return (T) method.invoke(obj, ArrayUtils.EMPTY_OBJECT_ARRAY);
} catch (Exception e) {
throw convertReflectionExceptionToUnchecked(e);
}
} else {
return (T) getFieldValue(obj, propertyName);
}
}
/**
* 先尝试用Setter函数写入, 如果不存在则直接写入变量, 按传入value的类型匹配函数.
*/
public static void setProperty(Object obj, String propertyName, final Object value) {
String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(propertyName);
Method method = getAccessibleMethod(obj, setterMethodName, value.getClass());
if (method != null) {
try {
method.invoke(obj, value);
} catch (Exception e) {
throw convertReflectionExceptionToUnchecked(e);
}
} else {
setFieldValue(obj, propertyName, value);
}
}
////////// 方法相关函数 //////
/**
* 直接调用对象方法, 无视private/protected修饰符.
*
* 根据传入参数的实际类型进行匹配
*
* 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用.
*/
public static <T> T invokeMethod(Object obj, String methodName, Object... args) {
args = ArrayUtils.nullToEmpty(args);
final Class<?>[] parameterTypes = ClassUtils.toClass(args);
return (T) invokeMethod(obj, methodName, args, parameterTypes);
}
/**
* 直接调用对象方法, 无视private/protected修饰符.
*
* 根据定义的参数类型进行匹配,
*
* 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用.
*/
public static Object invokeMethod(final Object obj, final String methodName, final Object[] args,
final Class<?>[] parameterTypes) {
Method method = getAccessibleMethod(obj, methodName, parameterTypes);
if (method == null) {
throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");
@@ -100,8 +162,11 @@ public class Reflections {
}
/**
* 直接调用对象方法, 无视private/protected修饰符, 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用.
* 只匹配函数名,如果有多个同名函数调用第一个。
* 直接调用对象方法, 无视private/protected修饰符
*
* 只匹配函数名,如果有多个同名函数调用第一个. 用于确信只有一个同名函数, 但参数类型不好确定的情况
*
* 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用.
*/
public static Object invokeMethodByName(final Object obj, final String methodName, final Object[] args) {
Method method = getAccessibleMethodByName(obj, methodName);
@@ -120,10 +185,12 @@ public class Reflections {
* 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问.
*
* 如向上转型到Object仍无法找到, 返回null.
*
* 因为class.getFiled(); 不能获取父类的private函数, 因此采用循环向上的getDeclaredField();
*/
public static Field getAccessibleField(final Object obj, final String fieldName) {
Validate.notNull(obj, "object can't be null");
Validate.notBlank(fieldName, "fieldName can't be blank");
Validate.notEmpty(fieldName, "fieldName can't be blank");
for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass
.getSuperclass()) {
try {
@@ -138,14 +205,20 @@ public class Reflections {
}
/**
* 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. 如向上转型到Object仍无法找到, 返回null. 匹配函数名+参数类型。
* 循环向上转型, 获取对象的DeclaredMethod, 并强制设置为可访问.
*
* 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
* 如向上转型到Object仍无法找到, 返回null.
*
* 匹配函数名+参数类型.
*
* 用于方法需要被多次调用的情况. 先使用本函数先取得Method, 然后调用Method.invoke(Object obj, Object... args)
*
* 因为class.getFiled() 不能获取父类的private函数, 因此采用循环向上的getDeclaredField();
*/
public static Method getAccessibleMethod(final Object obj, final String methodName,
final Class<?>... parameterTypes) {
public static Method getAccessibleMethod(final Object obj, final String methodName, Class<?>... parameterTypes) {
Validate.notNull(obj, "object can't be null");
Validate.notBlank(methodName, "methodName can't be blank");
Validate.notEmpty(methodName, "methodName can't be blank");
parameterTypes = ArrayUtils.nullToEmpty(parameterTypes);
for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType
.getSuperclass()) {
@@ -161,13 +234,19 @@ public class Reflections {
}
/**
* 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. 如向上转型到Object仍无法找到, 返回null. 只匹配函数名。
* 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
*
* 如向上转型到Object仍无法找到, 返回null.
*
* 只匹配函数名, 如果有多个同名函数返回第一个
*
* 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
*
* 因为class.getMethods() 不能获取父类的private函数, 因此采用循环向上的getMethods();
*/
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");
Validate.notEmpty(methodName, "methodName can't be blank");
for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType
.getSuperclass()) {
@@ -63,7 +63,7 @@ public class ReflectionsTest {
// 使用函数名+参数类型的匹配
assertThat(
Reflections
.invokeMethod(bean, "privateMethod", new Class[] { String.class }, new Object[] { "calvin" }))
.invokeMethod(bean, "privateMethod", new Object[] { "calvin" }, new Class[] { String.class }))
.isEqualTo("hello calvin");
// 仅匹配函数名
@@ -72,7 +72,7 @@ public class ReflectionsTest {
// 函数名错
try {
Reflections.invokeMethod(bean, "notExistMethod", new Class[] { String.class }, new Object[] { "calvin" });
Reflections.invokeMethod(bean, "notExistMethod", new Object[] { "calvin" }, new Class[] { String.class });
failBecauseExceptionWasNotThrown(IllegalArgumentException.class);
} catch (IllegalArgumentException e) {
@@ -80,7 +80,7 @@ public class ReflectionsTest {
// 参数类型错
try {
Reflections.invokeMethod(bean, "privateMethod", new Class[] { Integer.class }, new Object[] { "calvin" });
Reflections.invokeMethod(bean, "privateMethod", new Object[] { "calvin" }, new Class[] { Integer.class });
failBecauseExceptionWasNotThrown(RuntimeException.class);
} catch (RuntimeException e) {