ReflectUtils.java 14 KB

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