ReflectionUtils.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. package com.yaozhitech.spring5.common.util;
  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 org.apache.commons.lang3.StringUtils;
  9. import org.apache.commons.lang3.Validate;
  10. import org.slf4j.Logger;
  11. import org.slf4j.LoggerFactory;
  12. import org.springframework.util.Assert;
  13. /**
  14. * 反射工具类.
  15. * 提供调用getter/setter方法, 访问私有变量, 调用私有方法, 获取泛型类型Class, 被AOP过的真实类等工具函数.
  16. * @author calvin
  17. * @version 2013-01-15
  18. */
  19. @SuppressWarnings("rawtypes")
  20. public class ReflectionUtils {
  21. private static final String SETTER_PREFIX = "set";
  22. private static final String GETTER_PREFIX = "get";
  23. private static final String CGLIB_CLASS_SEPARATOR = "$$";
  24. private static Logger logger = LoggerFactory.getLogger(ReflectionUtils.class);
  25. /**
  26. * 调用Getter方法.
  27. * 支持多级,如:对象名.对象名.方法
  28. */
  29. public static Object invokeGetter(Object obj, String propertyName) {
  30. Object object = obj;
  31. for (String name : StringUtils.split(propertyName, ".")){
  32. String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);
  33. object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
  34. }
  35. return object;
  36. }
  37. /**
  38. * 调用Setter方法, 仅匹配方法名。
  39. * 支持多级,如:对象名.对象名.方法
  40. */
  41. public static void invokeSetter(Object obj, String propertyName, Object value) {
  42. Object object = obj;
  43. String[] names = StringUtils.split(propertyName, ".");
  44. for (int i=0; i<names.length; i++){
  45. if(i<names.length-1){
  46. String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);
  47. object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
  48. }else{
  49. String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);
  50. invokeMethodByName(object, setterMethodName, new Object[] { value });
  51. }
  52. }
  53. }
  54. /**
  55. * 直接读取对象属性值, 无视private/protected修饰符, 不经过getter函数.
  56. */
  57. public static Object getFieldValue(final Object obj, final String fieldName) {
  58. Field field = getAccessibleField(obj, fieldName);
  59. if (field == null) {
  60. throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]");
  61. }
  62. Object result = null;
  63. try {
  64. result = field.get(obj);
  65. } catch (IllegalAccessException e) {
  66. logger.error("不可能抛出的异常{}", e.getMessage());
  67. }
  68. return result;
  69. }
  70. /**
  71. * 直接设置对象属性值, 无视private/protected修饰符, 不经过setter函数.
  72. */
  73. public static void setFieldValue(final Object obj, final String fieldName, final Object value) {
  74. Field field = getAccessibleField(obj, fieldName);
  75. if (field == null) {
  76. logger.error("Could not find field [" + fieldName + "] on target [" + obj + "]");
  77. return;
  78. //throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + obj + "]");
  79. }
  80. try {
  81. field.set(obj, convert(value, field.getType()));
  82. } catch (IllegalAccessException e) {
  83. logger.error("不可能抛出的异常:{}", e.getMessage());
  84. }
  85. }
  86. public static Object convert(Object object, Class<?> type) {
  87. if (object instanceof Number) {
  88. Number number = (Number) object;
  89. if (type.equals(byte.class) || type.equals(Byte.class)) {
  90. return number.byteValue();
  91. }
  92. if (type.equals(short.class) || type.equals(Short.class)) {
  93. return number.shortValue();
  94. }
  95. if (type.equals(int.class) || type.equals(Integer.class)) {
  96. return number.intValue();
  97. }
  98. if (type.equals(long.class) || type.equals(Long.class)) {
  99. return number.longValue();
  100. }
  101. if (type.equals(float.class) || type.equals(Float.class)) {
  102. return number.floatValue();
  103. }
  104. if (type.equals(double.class) || type.equals(Double.class)) {
  105. return number.doubleValue();
  106. }
  107. }
  108. if(type.equals(String.class)){
  109. return object==null?"":object.toString();
  110. }
  111. return object;
  112. }
  113. /**
  114. * 直接调用对象方法, 无视private/protected修饰符.
  115. * 用于一次性调用的情况,否则应使用getAccessibleMethod()函数获得Method后反复调用.
  116. * 同时匹配方法名+参数类型,
  117. */
  118. public static Object invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,
  119. final Object[] args) {
  120. Method method = getAccessibleMethod(obj, methodName, parameterTypes);
  121. if (method == null) {
  122. throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");
  123. }
  124. try {
  125. return method.invoke(obj, args);
  126. } catch (Exception e) {
  127. throw convertReflectionExceptionToUnchecked(e);
  128. }
  129. }
  130. /**
  131. * 直接调用对象方法, 无视private/protected修饰符,
  132. * 用于一次性调用的情况,否则应使用getAccessibleMethodByName()函数获得Method后反复调用.
  133. * 只匹配函数名,如果有多个同名函数调用第一个。
  134. */
  135. public static Object invokeMethodByName(final Object obj, final String methodName, final Object[] args) {
  136. Method method = getAccessibleMethodByName(obj, methodName);
  137. if (method == null) {
  138. throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + obj + "]");
  139. }
  140. try {
  141. return method.invoke(obj, args);
  142. } catch (Exception e) {
  143. throw convertReflectionExceptionToUnchecked(e);
  144. }
  145. }
  146. /**
  147. * 循环向上转型, 获取对象的DeclaredField, 并强制设置为可访问.
  148. *
  149. * 如向上转型到Object仍无法找到, 返回null.
  150. */
  151. public static Field getAccessibleField(final Object obj, final String fieldName) {
  152. Validate.notNull(obj, "object can't be null");
  153. Validate.notBlank(fieldName, "fieldName can't be blank");
  154. for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
  155. try {
  156. Field field = superClass.getDeclaredField(fieldName);
  157. makeAccessible(field);
  158. return field;
  159. } catch (NoSuchFieldException e) {//NOSONAR
  160. // Field不在当前类定义,继续向上转型
  161. continue;// new add
  162. }
  163. }
  164. return null;
  165. }
  166. /**
  167. * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
  168. * 如向上转型到Object仍无法找到, 返回null.
  169. * 匹配函数名+参数类型。
  170. *
  171. * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
  172. */
  173. public static Method getAccessibleMethod(final Object obj, final String methodName,
  174. final Class<?>... parameterTypes) {
  175. Validate.notNull(obj, "object can't be null");
  176. Validate.notBlank(methodName, "methodName can't be blank");
  177. for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
  178. try {
  179. Method method = searchType.getDeclaredMethod(methodName, parameterTypes);
  180. makeAccessible(method);
  181. return method;
  182. } catch (NoSuchMethodException e) {
  183. // Method不在当前类定义,继续向上转型
  184. continue;// new add
  185. }
  186. }
  187. return null;
  188. }
  189. /**
  190. * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问.
  191. * 如向上转型到Object仍无法找到, 返回null.
  192. * 只匹配函数名。
  193. *
  194. * 用于方法需要被多次调用的情况. 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
  195. */
  196. public static Method getAccessibleMethodByName(final Object obj, final String methodName) {
  197. Validate.notNull(obj, "object can't be null");
  198. Validate.notBlank(methodName, "methodName can't be blank");
  199. for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass()) {
  200. Method[] methods = searchType.getDeclaredMethods();
  201. for (Method method : methods) {
  202. if (method.getName().equals(methodName)) {
  203. makeAccessible(method);
  204. return method;
  205. }
  206. }
  207. }
  208. return null;
  209. }
  210. /**
  211. * 改变private/protected的方法为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
  212. */
  213. public static void makeAccessible(Method method) {
  214. if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
  215. && !method.isAccessible()) {
  216. method.setAccessible(true);
  217. }
  218. }
  219. /**
  220. * 改变private/protected的成员变量为public,尽量不调用实际改动的语句,避免JDK的SecurityManager抱怨。
  221. */
  222. public static void makeAccessible(Field field) {
  223. if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers()) || Modifier
  224. .isFinal(field.getModifiers())) && !field.isAccessible()) {
  225. field.setAccessible(true);
  226. }
  227. }
  228. /**
  229. * 通过反射, 获得Class定义中声明的泛型参数的类型, 注意泛型必须定义在父类处
  230. * 如无法找到, 返回Object.class.
  231. * eg.
  232. * public UserDao extends HibernateDao<User>
  233. *
  234. * @param clazz The class to introspect
  235. * @return the first generic declaration, or Object.class if cannot be determined
  236. */
  237. @SuppressWarnings("unchecked")
  238. public static <T> Class<T> getClassGenricType(final Class clazz) {
  239. return getClassGenricType(clazz, 0);
  240. }
  241. /**
  242. * 通过反射, 获得Class定义中声明的父类的泛型参数的类型.
  243. * 如无法找到, 返回Object.class.
  244. *
  245. * 如public UserDao extends HibernateDao<User,Long>
  246. *
  247. * @param clazz clazz The class to introspect
  248. * @param index the Index of the generic ddeclaration,start from 0.
  249. * @return the index generic declaration, or Object.class if cannot be determined
  250. */
  251. public static Class getClassGenricType(final Class clazz, final int index) {
  252. Type genType = clazz.getGenericSuperclass();
  253. if (!(genType instanceof ParameterizedType)) {
  254. logger.warn(clazz.getSimpleName() + "'s superclass not ParameterizedType");
  255. return Object.class;
  256. }
  257. Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
  258. if (index >= params.length || index < 0) {
  259. logger.warn("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
  260. + params.length);
  261. return Object.class;
  262. }
  263. if (!(params[index] instanceof Class)) {
  264. logger.warn(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
  265. return Object.class;
  266. }
  267. return (Class) params[index];
  268. }
  269. public static Class<?> getUserClass(Object instance) {
  270. Assert.notNull(instance, "Instance must not be null");
  271. Class clazz = instance.getClass();
  272. if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR)) {
  273. Class<?> superClass = clazz.getSuperclass();
  274. if (superClass != null && !Object.class.equals(superClass)) {
  275. return superClass;
  276. }
  277. }
  278. return clazz;
  279. }
  280. /**
  281. * 将反射时的checked exception转换为unchecked exception.
  282. */
  283. public static RuntimeException convertReflectionExceptionToUnchecked(Exception e) {
  284. if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
  285. || e instanceof NoSuchMethodException) {
  286. return new IllegalArgumentException(e);
  287. } else if (e instanceof InvocationTargetException) {
  288. return new RuntimeException(((InvocationTargetException) e).getTargetException());
  289. } else if (e instanceof RuntimeException) {
  290. return (RuntimeException) e;
  291. }
  292. return new RuntimeException("Unexpected Checked Exception.", e);
  293. }
  294. /**
  295. * 判断某个对象是否拥有某个属性
  296. *
  297. * @param obj 对象
  298. * @param fieldName 属性名
  299. * @return 有属性返回true
  300. * 无属性返回false
  301. */
  302. public static boolean hasField(final Object obj, final String fieldName){
  303. Field field = getAccessibleField(obj, fieldName);
  304. if (field == null) {
  305. return false;
  306. }
  307. return true;
  308. }
  309. }