package cn.itcast.java.utils; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import org.apache.commons.beanutils.ConvertUtils; import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.beanutils.converters.DateConverter; import org.apache.commons.lang.StringUtils; /** * * 反射的 Utils 函數集合 * 提供訪問私有變量, 獲取泛型類型 Class, 提取集合中元素屬性等 Utils 函數 * */ public class ReflectionUtils { /** * 將反射時的 "檢查異常" 轉換爲 "運行時異常" * @return */ public static IllegalArgumentException convertToUncheckedException(Exception ex){ if(ex instanceof IllegalAccessException || ex instanceof IllegalArgumentException || ex instanceof NoSuchMethodException){ throw new IllegalArgumentException("反射異常", ex); }else{ throw new IllegalArgumentException(ex); } } /** * 轉換字符串類型到 toType 類型, 或 toType 轉爲字符串 * @param value: 待轉換的字符串 * @param toType: 提供類型信息的 Class, 能夠是基本數據類型的包裝類或指定格式日期型 * @return */ public static Object convertValue(Object value, Class<?> toType){ try { DateConverter dc = new DateConverter(); dc.setUseLocaleFormat(true); dc.setPatterns(new String[]{"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss"}); ConvertUtils.register(dc, Date.class); return ConvertUtils.convert(value, toType); } catch (Exception e) { e.printStackTrace(); throw convertToUncheckedException(e); } } /** * 提取集合中的對象的屬性(經過 getter 方法), 組成 List * @param collection: 來源集合 * @param propertyName: 要提取的屬性名 * @return */ @SuppressWarnings("unchecked") public static List fetchElementPropertyToList(Collection collection, String propertyName){ List list = new ArrayList(); try { for(Object obj: collection){ list.add(PropertyUtils.getProperty(obj, propertyName)); } } catch (Exception e) { e.printStackTrace(); convertToUncheckedException(e); } return list; } /** * 提取集合中的對象屬性(經過 getter 函數), 組合成由分隔符分隔的字符串 * @param collection: 來源集合 * @param propertyName: 要提取的屬性名 * @param seperator: 分隔符 * @return */ @SuppressWarnings("unchecked") public static String fetchElementPropertyToString(Collection collection, String propertyName, String seperator){ List list = fetchElementPropertyToList(collection, propertyName); return StringUtils.join(list, seperator); } /** * 經過反射, 得到定義 Class 時聲明的父類的泛型參數的類型 * 如: public EmployeeDao extends BaseDao<Employee, String> * @param clazz * @param index * @return */ @SuppressWarnings("unchecked") public static Class getSuperClassGenricType(Class clazz, int index){ Type genType = clazz.getGenericSuperclass(); if(!(genType instanceof ParameterizedType)){ return Object.class; } Type [] params = ((ParameterizedType)genType).getActualTypeArguments(); if(index >= params.length || index < 0){ return Object.class; } if(!(params[index] instanceof Class)){ return Object.class; } return (Class) params[index]; } /** * 經過反射, 得到 Class 定義中聲明的父類的泛型參數類型 * 如: public EmployeeDao extends BaseDao<Employee, String> * @param <T> * @param clazz * @return */ @SuppressWarnings("unchecked") public static<T> Class<T> getSuperGenericType(Class clazz){ return getSuperClassGenricType(clazz, 0); } /** * 循環向上轉型, 獲取對象的 DeclaredMethod * @param object * @param methodName * @param parameterTypes * @return */ public static Method getDeclaredMethod(Object object, String methodName, Class<?>[] parameterTypes){ for(Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()){ try { //superClass.getMeth(methodName, parameterTypes); return superClass.getDeclaredMethod(methodName, parameterTypes); } catch (NoSuchMethodException e) { //Method 不在當前類定義, 繼續向上轉型 } } return null; } /** * 使 filed 變爲可訪問 * @param field */ public static void makeAccessible(Field field){ if(!Modifier.isPublic(field.getModifiers())){ field.setAccessible(true); } } /** * 循環向上轉型, 獲取對象的 DeclaredField * @param object * @param filedName * @return */ public static Field getDeclaredField(Object object, String filedName){ for(Class<?> superClass = object.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()){ try { return superClass.getDeclaredField(filedName); } catch (NoSuchFieldException e) { //Field 不在當前類定義, 繼續向上轉型 } } return null; } /** * 直接調用對象方法, 而忽略修飾符(private, protected) * @param object * @param methodName * @param parameterTypes * @param parameters * @return * @throws InvocationTargetException * @throws IllegalArgumentException */ public static Object invokeMethod(Object object, String methodName, Class<?> [] parameterTypes,Object [] parameters) throws InvocationTargetException{ Method method = getDeclaredMethod(object, methodName, parameterTypes); if(method == null){ throw new IllegalArgumentException("Could not find method [" + methodName + "] on target [" + object + "]"); } method.setAccessible(true); try { return method.invoke(object, parameters); } catch(IllegalAccessException e) { } return null; } /** * 直接設置對象屬性值, 忽略 private/protected 修飾符, 也不通過 setter * @param object * @param fieldName * @param value */ public static void setFieldValue(Object object, String fieldName, Object value){ Field field = getDeclaredField(object, fieldName); if (field == null) throw new IllegalArgumentException("Could not find field [" + fieldName + "] on target [" + object + "]"); makeAccessible(field); try { field.set(object, value); } catch (IllegalAccessException e) { } } /** * 直接讀取對象的屬性值, 忽略 private/protected 修飾符, 也不通過 getter * @param object * @param fieldName * @return */ public static Object getFieldValue(Object object, String fieldName){ Field field = getDeclaredField(object, fieldName); if (field == null) throw new IllegalArgumentException ("Could not find field [" + fieldName + "] on target [" + object + "]"); makeAccessible(field); Object result = null; try { result = field.get(object); } catch (IllegalAccessException e) { } return result; } }