mybatis封裝了本身的反射類工具箱。java
Reflector類中:數組
構造方法以下:解析指定class隊形,填充以下集合緩存
public Reflector(Class<?> clazz) { type = clazz;//初始化clazz字段 addDefaultConstructor(clazz);//查找clazz默認構造方法 addGetMethods(clazz);//處理clazz中getter方法,填充getMethods集合和getTypes集合 addSetMethods(clazz);//處理clazz中setter方法,填充setMethods集合和setTypes集合 addFields(clazz);//處理無setter/getter方法的字段 //根據getMethods/setMethods集合,初始化可讀/寫屬性的名稱集合 readablePropertyNames = getMethods.keySet().toArray(new String[getMethods.keySet().size()]); writeablePropertyNames = setMethods.keySet().toArray(new String[setMethods.keySet().size()]); for (String propName : readablePropertyNames) {//初始化caseInsensitivePropertyMap(記錄了全部屬性名稱)集合,其中記錄了全部大寫格式屬性名稱 caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName); } for (String propName : writeablePropertyNames) { caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName); } }
調用了安全
private void addDefaultConstructor(Class<?> clazz) { Constructor<?>[] consts = clazz.getDeclaredConstructors();//獲取構造方法的參數類型 for (Constructor<?> constructor : consts) { if (constructor.getParameterTypes().length == 0) {//若爲無參構造函數(默認構造函數) if (canAccessPrivateMethods()) {//安全管理器已作檢查經過則返回ture不然拋出異常返回false try { constructor.setAccessible(true);//將 accessible 標誌設置爲指示的布爾值,值爲 true 則指示反射的對象在使用時應該取消 Java 語言訪問檢查,從而提升了性能。值爲 false 則指示反射的對象應該實施 Java 語言訪問檢查。 } catch (Exception e) { // Ignored. This is only a final precaution, nothing we can do. 忽略。 這只是最後的預防措施,咱們作不了什麼。 } } if (constructor.isAccessible()) {//獲取上面的Accessible的flag值(true或者false) this.defaultConstructor = constructor; } } } }
addGetMethods()解析類中定義的getter方法mybatis
先調用getClassMethods,以下所示,接着app
private Method[] getClassMethods(Class<?> cls) {//該方法獲取當前類及父類中定義的全部方法的惟一簽名和對應Method對象 //用於記錄指定類中定義的所有方法的惟一簽名及對應Method對象 Map<String, Method> uniqueMethods = new HashMap<String, Method>(); Class<?> currentClass = cls; while (currentClass != null) { //記錄currentClass類中定義的所有方法 addUniqueMethods(uniqueMethods, currentClass.getDeclaredMethods()); //記錄接口中定義方法 // we also need to look for interface methods - // because the class may be abstract Class<?>[] interfaces = currentClass.getInterfaces(); for (Class<?> anInterface : interfaces) { addUniqueMethods(uniqueMethods, anInterface.getMethods()); } currentClass = currentClass.getSuperclass();//獲取父類繼續循環 } Collection<Method> methods = uniqueMethods.values(); return methods.toArray(new Method[methods.size()]);//轉成methods數組返回 }
//返回值類型#方法名稱:參數類型列表。例如:Reflector.getSignature(Method)方法惟一簽名是:java.lang.String#getSignature:java.lang.reflect.Method private String getSignature(Method method) { StringBuilder sb = new StringBuilder(); //該對象返回值類型 Class<?> returnType = method.getReturnType(); if (returnType != null) { sb.append(returnType.getName()).append('#'); } sb.append(method.getName()); //該對象表示的方法的參數類型 Class<?>[] parameters = method.getParameterTypes(); for (int i = 0; i < parameters.length; i++) { if (i == 0) { sb.append(':'); } else { sb.append(','); } sb.append(parameters[i].getName()); } return sb.toString(); }
private void addUniqueMethods(Map<String, Method> uniqueMethods, Method[] methods) {//爲每一個方法生成惟一簽名,記錄到uniqueMethods集合中 for (Method currentMethod : methods) { if (!currentMethod.isBridge()) {//橋接方法,JDK 1.5 引入泛型後,爲了使Java的泛型方法生成的字節碼和 1.5 版本前的字節碼相兼容,由編譯器自動生成的方法 String signature = getSignature(currentMethod); // check to see if the method is already known // if it is known, then an extended class must have // overridden a method //檢測是否在子類中已經添加了這個方法,若添加過,則表示子類覆寫了這個方法,則不用再向uniqueMethods集合中添加這個方法了 if (!uniqueMethods.containsKey(signature)) { if (canAccessPrivateMethods()) {//安全管理器已作檢查經過則返回ture不然拋出異常返回false try { currentMethod.setAccessible(true);//將 accessible 標誌設置爲指示的布爾值,值爲 true 則指示反射的對象在使用時應該取消 Java 語言訪問檢查,從而提升了性能。值爲 false 則指示反射的對象應該實施 Java 語言訪問檢查。 } catch (Exception e) { // Ignored. This is only a final precaution, nothing we can do. //忽略。 這只是最後的預防措施,咱們作不了什麼 } } //記錄該簽名和方法的對應關係 uniqueMethods.put(signature, currentMethod); } } } }
/** 解決衝突 */ private void resolveGetterConflicts(Map<String, List<Method>> conflictingGetters) { for (Entry<String, List<Method>> entry : conflictingGetters.entrySet()) { Method winner = null; String propName = entry.getKey(); for (Method candidate : entry.getValue()) { if (winner == null) { winner = candidate; continue; } // 獲取返回值類型 Class<?> winnerType = winner.getReturnType(); Class<?> candidateType = candidate.getReturnType(); /* * 兩個方法的返回值類型一致,若兩個方法返回值類型均爲 boolean,則選取 isXXX 方法 * 爲 winner。不然沒法決定哪一個方法更爲合適,只能拋出異常 */ if (candidateType.equals(winnerType)) { if (!boolean.class.equals(candidateType)) { throw new ReflectionException( "Illegal overloaded getter method with ambiguous type for property " + propName + " in class " + winner.getDeclaringClass() + ". This breaks the JavaBeans specification and can cause unpredictable results."); /* * 若是方法返回值類型爲 boolean,且方法名以 "is" 開頭, * 則認爲候選方法 candidate 更爲合適 */ } else if (candidate.getName().startsWith("is")) { winner = candidate; } /* * winnerType 是 candidateType 的子類,類型上更爲具體, * 則認爲當前的 winner 還是合適的,無需作什麼事情 */ } else if (candidateType.isAssignableFrom(winnerType)) { /* * candidateType 是 winnerType 的子類,此時認爲 candidate 方法更爲合適, * 故將 winner 更新爲 candidate */ } else if (winnerType.isAssignableFrom(candidateType)) { winner = candidate; } else { throw new ReflectionException( "Illegal overloaded getter method with ambiguous type for property " + propName + " in class " + winner.getDeclaringClass() + ". This breaks the JavaBeans specification and can cause unpredictable results."); } } // 將篩選出的方法添加到 getMethods 中,並將方法返回值添加到 getTypes 中 addGetMethod(propName, winner); } }
private void addGetMethod(String name, Method method) { if (isValidPropertyName(name)) {//檢測屬性名是否合法,即屬性名不能以'$'開頭且不能等於'class','serialVersionUID' getMethods.put(name, new MethodInvoker(method));//將屬性名及對應MethodInvoker對象添加到getMethods集合中 Type returnType = TypeParameterResolver.resolveReturnType(method, type);//獲取返回值type getTypes.put(name, typeToClass(returnType));//將屬性名及getter方法返回值類型添加到getTypes集合中保存 } }
private void addGetMethods(Class<?> cls) { Map<String, List<Method>> conflictingGetters = new HashMap<String, List<Method>>(); //conflictingGetters 集合key是屬性名,value是getter方法集合,因爲子類可能覆寫父類getter方法,因此同一屬性名會有多個getter方法 Method[] methods = getClassMethods(cls);//獲取制定類及父類和接口中定義的方法 for (Method method : methods) {// if (method.getParameterTypes().length > 0) { continue; } String name = method.getName(); //javaBean中getter方法的方法名長度以"get"開頭而且長度大於3或者以"is"開頭而且長度大於2 if ((name.startsWith("get") && name.length() > 3) || (name.startsWith("is") && name.length() > 2)) { name = PropertyNamer.methodToProperty(name);//截取掉get或者is獲取後面實際的對應屬性名稱 addMethodConflict(conflictingGetters, name, method);//若此方法在conflictingGetters中沒有,則放入key是屬性名 和value 是getter方法集合不然只放入list集合中的方法 } } resolveGetterConflicts(conflictingGetters);//調用上面解決衝突的方法 }
private void addFields(Class<?> clazz) {//處理類中定義全部字段,並在處理後添加到setMethods集合,setTypes集合,getMethods集合以及getTypes集合中 Field[] fields = clazz.getDeclaredFields();//獲取clazz中定義的全部字段 for (Field field : fields) { if (canAccessPrivateMethods()) {//安全管理器已作檢查經過則返回ture不然拋出異常返回false try { field.setAccessible(true);//將 accessible 標誌設置爲指示的布爾值,值爲 true 則指示反射的對象在使用時應該取消 Java 語言訪問檢查,從而提升了性能。值爲 false 則指示反射的對象應該實施 Java 語言訪問檢查。 } catch (Exception e) { // Ignored. This is only a final precaution, nothing we can do. //忽略。 這只是最後的預防措施,咱們作不了什麼 } } if (field.isAccessible()) {當字段修飾符爲private時,咱們須要加上,不然會拋出異常 if (!setMethods.containsKey(field.getName())) {//當setMethods集合不包含同名屬性時,將其記錄到setMethods集合和setTypes集合 // issue #379 - removed the check for final because JDK 1.5 allows // modification of final fields through reflection (JSR-133). (JGB) // pr #16 - final static can only be set by the classloader int modifiers = field.getModifiers();//該字段的修飾符 if (!(Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers))) {//過濾掉final和static修飾的字段 addSetField(field);//填充setMethods集合和setTypes集合,與上述addGetMethod相似 } } if (!getMethods.containsKey(field.getName())) {//當getMethods集合不包含同名屬性時,將其記錄到getMethods集合和getTypes集合 addGetField(field);//填充getMethods集合和getTypes集合,與上述addGetMethod相似 } } } if (clazz.getSuperclass() != null) {//有父類 addFields(clazz.getSuperclass());//遞歸調用,處理父類中定義字段 } }
Invoker:ide
public interface Invoker { Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException;//調用獲取指定字段或執行的方法 Class<?> getType();//返回屬性相應類型 }
只有三個實現以下:函數
public class GetFieldInvoker implements Invoker { private final Field field; public GetFieldInvoker(Field field) { this.field = field; } @Override public Object invoke(Object target, Object[] args) throws IllegalAccessException, InvocationTargetException { return field.get(target);//方法返回指定對象上由此Field表示的字段的值。若是該對象具備原始類型,則該值將自動包裝在對象中。 } @Override public Class<?> getType() { return field.getType(); } }
SetFieldInvoker與GetFieldInvoker相相似工具
MethodInvoker的invoker調用Method.invoker實現的性能
由ReflectorFactory接口實現對Reflector對象建立與緩存
public interface ReflectorFactory { boolean isClassCacheEnabled();//該ReflectorFactory對象是否緩存Reflector對象 void setClassCacheEnabled(boolean classCacheEnabled);//設置是否緩存Reflector對象 Reflector findForClass(Class<?> type);//建立指定Class對應的Reflector對象 }
只有一個實現上述接口的實現類:DefaultReflectorFactory
public class DefaultReflectorFactory implements ReflectorFactory { private boolean classCacheEnabled = true;//是否開啓對Reflector對象的緩存 private final ConcurrentMap<Class<?>, Reflector> reflectorMap = new ConcurrentHashMap<Class<?>, Reflector>();//使用ConcurrentMap集合實現對 Reflector對象的緩存 public DefaultReflectorFactory() { } @Override public boolean isClassCacheEnabled() { return classCacheEnabled; } @Override public void setClassCacheEnabled(boolean classCacheEnabled) { this.classCacheEnabled = classCacheEnabled; } @Override public Reflector findForClass(Class<?> type) { if (classCacheEnabled) {//是否開啓緩存 // synchronized (type) removed see issue #461 Reflector cached = reflectorMap.get(type); if (cached == null) { cached = new Reflector(type);//建立Reflector對象 reflectorMap.put(type, cached);//放入ConcurrentMap中緩存 } return cached; } else { return new Reflector(type);//沒開啓緩存則直接建立新對象返回 } } }