#525 加强Utils Modules模块:自家的Reflections更新
This commit is contained in:
@@ -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>
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ package org.springside.modules.utils.base;
|
||||
*
|
||||
* @author calvin
|
||||
*/
|
||||
public class PropertiesUtil {
|
||||
public class SystemProperties {
|
||||
|
||||
/////////// Boolean.readBoolean()扩展 ///////////////
|
||||
|
||||
+103
-24
@@ -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()) {
|
||||
|
||||
+3
-3
@@ -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) {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user