ReflectUtils.java 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. package com.future.common.utils.reflect;
  2. import com.future.common.core.text.Convert;
  3. import com.future.common.utils.DateUtils;
  4. import org.apache.commons.lang3.StringUtils;
  5. import org.apache.commons.lang3.Validate;
  6. import org.apache.poi.ss.usermodel.DateUtil;
  7. import org.slf4j.Logger;
  8. import org.slf4j.LoggerFactory;
  9. import java.lang.reflect.*;
  10. import java.util.Date;
  11. /**
  12. * 反射工具类. 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数.
  13. *
  14. * @author future
  15. */
  16. @SuppressWarnings("rawtypes")
  17. public class ReflectUtils
  18. {
  19. private static final String SETTER_PREFIX = "set";
  20. private static final String GETTER_PREFIX = "get";
  21. private static final String CGLIB_CLASS_SEPARATOR = "$$";
  22. private static Logger logger = LoggerFactory.getLogger(ReflectUtils.class);
  23. /**
  24. * 调用Getter方法.
  25. * 支持多级,如:对象名.对象名.方法
  26. */
  27. @SuppressWarnings("unchecked")
  28. public static <E> E invokeGetter(Object obj, String propertyName)
  29. {
  30. Object object = obj;
  31. for (String name : StringUtils.split(propertyName, "."))
  32. {
  33. String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);
  34. object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
  35. }
  36. return (E) object;
  37. }
  38. /**
  39. * 调用Setter方法, 仅匹配方法名。
  40. * 支持多级,如:对象名.对象名.方法
  41. */
  42. public static <E> void invokeSetter(Object obj, String propertyName, E value)
  43. {
  44. Object object = obj;
  45. String[] names = StringUtils.split(propertyName, ".");
  46. for (int i = 0; i < names.length; i++)
  47. {
  48. if (i < names.length - 1)
  49. {
  50. String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);
  51. object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
  52. }
  53. else
  54. {
  55. String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);
  56. invokeMethodByName(object, setterMethodName, new Object[] { value });
  57. }
  58. }
  59. }
  60. /**
  61. * 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数.
  62. */
  63. @SuppressWarnings("unchecked")
  64. public static <E> E getFieldValue(final Object obj, final String fieldName)
  65. {
  66. Field field = getAccessibleField(obj, fieldName);
  67. if (field == null)
  68. {
  69. logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 ");
  70. return null;
  71. }
  72. E result = null;
  73. try
  74. {
  75. result = (E) field.get(obj);
  76. }
  77. catch (IllegalAccessException e)
  78. {
  79. logger.error("不可能抛出的异常{}", e.getMessage());
  80. }
  81. return result;
  82. }
  83. /**
  84. * 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数.
  85. */
  86. public static <E> void setFieldValue(final Object obj, final String fieldName, final E value)
  87. {
  88. Field field = getAccessibleField(obj, fieldName);
  89. if (field == null)
  90. {
  91. // throw new IllegalArgumentException("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 ");
  92. logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + fieldName + "] 字段 ");
  93. return;
  94. }
  95. try
  96. {
  97. field.set(obj, value);
  98. }
  99. catch (IllegalAccessException e)
  100. {
  101. logger.error("不可能抛出的异常: {}", e.getMessage());
  102. }
  103. }
  104. /**
  105. * 直接调用对象方法, 无视private/protected修饰符.
  106. * 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用.
  107. * 同时匹配方法名+参数类型,
  108. */
  109. @SuppressWarnings("unchecked")
  110. public static <E> E invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,
  111. final Object[] args)
  112. {
  113. if (obj == null || methodName == null)
  114. {
  115. return null;
  116. }
  117. Method method = getAccessibleMethod(obj, methodName, parameterTypes);
  118. if (method == null)
  119. {
  120. logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 ");
  121. return null;
  122. }
  123. try
  124. {
  125. return (E) method.invoke(obj, args);
  126. }
  127. catch (Exception e)
  128. {
  129. String msg = "method: " + method + ", obj: " + obj + ", args: " + args + "";
  130. throw convertReflectionExceptionToUnchecked(msg, e);
  131. }
  132. }
  133. /**
  134. * 直接调用对象方法, 无视private/protected修饰符,
  135. * 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用.
  136. * 只匹配函数名,如果有多个同名函数调用第一个。
  137. */
  138. @SuppressWarnings("unchecked")
  139. public static <E> E invokeMethodByName(final Object obj, final String methodName, final Object[] args)
  140. {
  141. Method method = getAccessibleMethodByName(obj, methodName, args.length);
  142. if (method == null)
  143. {
  144. // 如果为空不报错,直接返回空。
  145. logger.debug("在 [" + obj.getClass() + "] 中,没有找到 [" + methodName + "] 方法 ");
  146. return null;
  147. }
  148. try
  149. {
  150. // 类型转换(将参数数据类型转换为目标方法参数类型)
  151. Class<?>[] cs = method.getParameterTypes();
  152. for (int i = 0; i < cs.length; i++)
  153. {
  154. if (args[i] != null && !args[i].getClass().equals(cs[i]))
  155. {
  156. if (cs[i] == String.class)
  157. {
  158. args[i] = Convert.toStr(args[i]);
  159. if (StringUtils.endsWith((String) args[i], ".0"))
  160. {
  161. args[i] = StringUtils.substringBefore((String) args[i], ".0");
  162. }
  163. }
  164. else if (cs[i] == Integer.class)
  165. {
  166. args[i] = Convert.toInt(args[i]);
  167. }
  168. else if (cs[i] == Long.class)
  169. {
  170. args[i] = Convert.toLong(args[i]);
  171. }
  172. else if (cs[i] == Double.class)
  173. {
  174. args[i] = Convert.toDouble(args[i]);
  175. }
  176. else if (cs[i] == Float.class)
  177. {
  178. args[i] = Convert.toFloat(args[i]);
  179. }
  180. else if (cs[i] == Date.class)
  181. {
  182. if (args[i] instanceof String)
  183. {
  184. args[i] = DateUtils.parseDate(args[i]);
  185. }
  186. else
  187. {
  188. args[i] = DateUtil.getJavaDate((Double) args[i]);
  189. }
  190. }
  191. else if (cs[i] == boolean.class || cs[i] == Boolean.class)
  192. {
  193. args[i] = Convert.toBool(args[i]);
  194. }
  195. }
  196. }
  197. return (E) method.invoke(obj, args);
  198. }
  199. catch (Exception e)
  200. {
  201. String msg = "method: " + method + ", obj: " + obj + ", args: " + args + "";
  202. throw convertReflectionExceptionToUnchecked(msg, e);
  203. }
  204. }
  205. /**
  206. * 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问.
  207. * 如向上转型到Object仍无法找到, 返回null.
  208. */
  209. public static Field getAccessibleField(final Object obj, final String fieldName)
  210. {
  211. // 为空不报错。直接返回 null
  212. if (obj == null)
  213. {
  214. return null;
  215. }
  216. Validate.notBlank(fieldName, "fieldName can't be blank");
  217. for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass())
  218. {
  219. try
  220. {
  221. Field field = superClass.getDeclaredField(fieldName);
  222. makeAccessible(field);
  223. return field;
  224. }
  225. catch (NoSuchFieldException e)
  226. {
  227. continue;
  228. }
  229. }
  230. return null;
  231. }
  232. /**
  233. * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
  234. * 如向上转型到Object仍无法找到, 返回null.
  235. * 匹配函数名+参数类型。
  236. * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
  237. */
  238. public static Method getAccessibleMethod(final Object obj, final String methodName,
  239. final Class<?>... parameterTypes)
  240. {
  241. // 为空不报错。直接返回 null
  242. if (obj == null)
  243. {
  244. return null;
  245. }
  246. Validate.notBlank(methodName, "methodName can't be blank");
  247. for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass())
  248. {
  249. try
  250. {
  251. Method method = searchType.getDeclaredMethod(methodName, parameterTypes);
  252. makeAccessible(method);
  253. return method;
  254. }
  255. catch (NoSuchMethodException e)
  256. {
  257. continue;
  258. }
  259. }
  260. return null;
  261. }
  262. /**
  263. * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
  264. * 如向上转型到Object仍无法找到, 返回null.
  265. * 只匹配函数名。
  266. * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
  267. */
  268. public static Method getAccessibleMethodByName(final Object obj, final String methodName, int argsNum)
  269. {
  270. // 为空不报错。直接返回 null
  271. if (obj == null)
  272. {
  273. return null;
  274. }
  275. Validate.notBlank(methodName, "methodName can't be blank");
  276. for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass())
  277. {
  278. Method[] methods = searchType.getDeclaredMethods();
  279. for (Method method : methods)
  280. {
  281. if (method.getName().equals(methodName) && method.getParameterTypes().length == argsNum)
  282. {
  283. makeAccessible(method);
  284. return method;
  285. }
  286. }
  287. }
  288. return null;
  289. }
  290. /**
  291. * 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
  292. */
  293. public static void makeAccessible(Method method)
  294. {
  295. if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
  296. && !method.isAccessible())
  297. {
  298. method.setAccessible(true);
  299. }
  300. }
  301. /**
  302. * 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
  303. */
  304. public static void makeAccessible(Field field)
  305. {
  306. if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())
  307. || Modifier.isFinal(field.getModifiers())) && !field.isAccessible())
  308. {
  309. field.setAccessible(true);
  310. }
  311. }
  312. /**
  313. * 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处
  314. * 如无法找到, 返回Object.class.
  315. */
  316. @SuppressWarnings("unchecked")
  317. public static <T> Class<T> getClassGenricType(final Class clazz)
  318. {
  319. return getClassGenricType(clazz, 0);
  320. }
  321. /**
  322. * 通过反射, 获得Class定义中声明的父类的泛型参数的类型.
  323. * 如无法找到, 返回Object.class.
  324. */
  325. public static Class getClassGenricType(final Class clazz, final int index)
  326. {
  327. Type genType = clazz.getGenericSuperclass();
  328. if (!(genType instanceof ParameterizedType))
  329. {
  330. logger.debug(clazz.getSimpleName() + "'s superclass not ParameterizedType");
  331. return Object.class;
  332. }
  333. Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
  334. if (index >= params.length || index < 0)
  335. {
  336. logger.debug("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
  337. + params.length);
  338. return Object.class;
  339. }
  340. if (!(params[index] instanceof Class))
  341. {
  342. logger.debug(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
  343. return Object.class;
  344. }
  345. return (Class) params[index];
  346. }
  347. public static Class<?> getUserClass(Object instance)
  348. {
  349. if (instance == null)
  350. {
  351. throw new RuntimeException("Instance must not be null");
  352. }
  353. Class clazz = instance.getClass();
  354. if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR))
  355. {
  356. Class<?> superClass = clazz.getSuperclass();
  357. if (superClass != null && !Object.class.equals(superClass))
  358. {
  359. return superClass;
  360. }
  361. }
  362. return clazz;
  363. }
  364. /**
  365. * 将反射时的checked exception转换为unchecked exception.
  366. */
  367. public static RuntimeException convertReflectionExceptionToUnchecked(String msg, Exception e)
  368. {
  369. if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
  370. || e instanceof NoSuchMethodException)
  371. {
  372. return new IllegalArgumentException(msg, e);
  373. }
  374. else if (e instanceof InvocationTargetException)
  375. {
  376. return new RuntimeException(msg, ((InvocationTargetException) e).getTargetException());
  377. }
  378. return new RuntimeException(msg, e);
  379. }
  380. }