ReflectUtils.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  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. else if (cs[i] == boolean.class || cs[i] == Boolean.class)
  197. {
  198. args[i] = Convert.toBool(args[i]);
  199. }
  200. }
  201. }
  202. return (E) method.invoke(obj, args);
  203. }
  204. catch (Exception e)
  205. {
  206. String msg = "method: " + method + ", obj: " + obj + ", args: " + args + "";
  207. throw convertReflectionExceptionToUnchecked(msg, e);
  208. }
  209. }
  210. /**
  211. * 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问.
  212. * 如向上转型到Object仍无法找到, 返回null.
  213. */
  214. public static Field getAccessibleField(final Object obj, final String fieldName)
  215. {
  216. // 为空不报错。直接返回 null
  217. if (obj == null)
  218. {
  219. return null;
  220. }
  221. Validate.notBlank(fieldName, "fieldName can't be blank");
  222. for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass())
  223. {
  224. try
  225. {
  226. Field field = superClass.getDeclaredField(fieldName);
  227. makeAccessible(field);
  228. return field;
  229. }
  230. catch (NoSuchFieldException e)
  231. {
  232. continue;
  233. }
  234. }
  235. return null;
  236. }
  237. /**
  238. * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
  239. * 如向上转型到Object仍无法找到, 返回null.
  240. * 匹配函数名+参数类型。
  241. * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
  242. */
  243. public static Method getAccessibleMethod(final Object obj, final String methodName,
  244. final Class<?>... parameterTypes)
  245. {
  246. // 为空不报错。直接返回 null
  247. if (obj == null)
  248. {
  249. return null;
  250. }
  251. Validate.notBlank(methodName, "methodName can't be blank");
  252. for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass())
  253. {
  254. try
  255. {
  256. Method method = searchType.getDeclaredMethod(methodName, parameterTypes);
  257. makeAccessible(method);
  258. return method;
  259. }
  260. catch (NoSuchMethodException e)
  261. {
  262. continue;
  263. }
  264. }
  265. return null;
  266. }
  267. /**
  268. * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
  269. * 如向上转型到Object仍无法找到, 返回null.
  270. * 只匹配函数名。
  271. * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
  272. */
  273. public static Method getAccessibleMethodByName(final Object obj, final String methodName, int argsNum)
  274. {
  275. // 为空不报错。直接返回 null
  276. if (obj == null)
  277. {
  278. return null;
  279. }
  280. Validate.notBlank(methodName, "methodName can't be blank");
  281. for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass())
  282. {
  283. Method[] methods = searchType.getDeclaredMethods();
  284. for (Method method : methods)
  285. {
  286. if (method.getName().equals(methodName) && method.getParameterTypes().length == argsNum)
  287. {
  288. makeAccessible(method);
  289. return method;
  290. }
  291. }
  292. }
  293. return null;
  294. }
  295. /**
  296. * 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
  297. */
  298. public static void makeAccessible(Method method)
  299. {
  300. if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
  301. && !method.isAccessible())
  302. {
  303. method.setAccessible(true);
  304. }
  305. }
  306. /**
  307. * 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
  308. */
  309. public static void makeAccessible(Field field)
  310. {
  311. if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())
  312. || Modifier.isFinal(field.getModifiers())) && !field.isAccessible())
  313. {
  314. field.setAccessible(true);
  315. }
  316. }
  317. /**
  318. * 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处
  319. * 如无法找到, 返回Object.class.
  320. */
  321. @SuppressWarnings("unchecked")
  322. public static <T> Class<T> getClassGenricType(final Class clazz)
  323. {
  324. return getClassGenricType(clazz, 0);
  325. }
  326. /**
  327. * 通过反射, 获得Class定义中声明的父类的泛型参数的类型.
  328. * 如无法找到, 返回Object.class.
  329. */
  330. public static Class getClassGenricType(final Class clazz, final int index)
  331. {
  332. Type genType = clazz.getGenericSuperclass();
  333. if (!(genType instanceof ParameterizedType))
  334. {
  335. logger.debug(clazz.getSimpleName() + "'s superclass not ParameterizedType");
  336. return Object.class;
  337. }
  338. Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
  339. if (index >= params.length || index < 0)
  340. {
  341. logger.debug("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
  342. + params.length);
  343. return Object.class;
  344. }
  345. if (!(params[index] instanceof Class))
  346. {
  347. logger.debug(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
  348. return Object.class;
  349. }
  350. return (Class) params[index];
  351. }
  352. public static Class<?> getUserClass(Object instance)
  353. {
  354. if (instance == null)
  355. {
  356. throw new RuntimeException("Instance must not be null");
  357. }
  358. Class clazz = instance.getClass();
  359. if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR))
  360. {
  361. Class<?> superClass = clazz.getSuperclass();
  362. if (superClass != null && !Object.class.equals(superClass))
  363. {
  364. return superClass;
  365. }
  366. }
  367. return clazz;
  368. }
  369. /**
  370. * 将反射时的checked exception转换为unchecked exception.
  371. */
  372. public static RuntimeException convertReflectionExceptionToUnchecked(String msg, Exception e)
  373. {
  374. if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
  375. || e instanceof NoSuchMethodException)
  376. {
  377. return new IllegalArgumentException(msg, e);
  378. }
  379. else if (e instanceof InvocationTargetException)
  380. {
  381. return new RuntimeException(msg, ((InvocationTargetException) e).getTargetException());
  382. }
  383. return new RuntimeException(msg, e);
  384. }
  385. }