深入理解java反射機制中Method類中的invoke()方法
1.先說明Method類中的幾個重要的屬性
1)Method型別的root屬性:
可以理解為每一個 java方法都有唯一的一個Method物件,這個物件就是root,我們可以利用反射建立java方法的眾多的Method類的物件,這些物件指向root,可以理解為root的映象。
2)MethodAccessor型別的 methodAccessor屬性:
每一個Method物件有一個root屬性,每一個root物件裡有一個methodAccessor物件。我們獲取的Method相當於root的映象,可以共用methodAccessor物件。這個物件由ReflectionFactory來建立
2.原始碼分析
首先是判斷override是true還是false,override屬性是Method類的父類Executable的父類AccessibleObject的一個屬性,用來判斷是否要進行訪問許可權判斷。預設為false,我們可以通過setAccessible()方法來設定override的值。它裡面有一個setAccessible0()方法:
如果override設定為true,則可以忽略訪問許可權的限制,直接呼叫。如果為false,則通過執行Reflection.quickCheckMemberAccess(clazz, modifiers)這個方法來判斷我們需要呼叫的方法是不是public型別的(還是訪問許可權的問題,public,protected,private的範圍)。如果不是public型別的,則我們通過 Class<?> caller = Reflection.getCallerClass();來獲取該方法的Class物件。然後呼叫checkAccess(caller, clazz, obj, modifiers);進行訪問許可權的校驗。
在這個訪問許可權的校驗方法中我們用到了快取,即第一次校驗後就存放到快取中,下次進行快取校驗時如果還是同一個類來校驗,則不校驗,直接返回。但是如果下一次不是同一個類,我們會覆蓋快取中的類。
訪問許可權的判斷校驗後就是重點:
首先我們會獲取methodAccessor物件,因為每個java方法的methodAccessor唯一。此處我們通過acquireMethodAccessor()來生成methodAccessor物件:
如果root中的methodAccessor不為空,即上次呼叫invoke()已經為root中的methodAccessor賦值了。否則通過reflectionFactory.newMethodAccessor(this);來建立methodAccessor物件,然後呼叫setMethodAccessor(tmp);為root中的methodAccessor賦值。然後通過methodAccessor物件的invoke()來完成對方法的呼叫。實際上Method.invoke()不是自己來完成反射呼叫邏輯的,而是委託給MethodAccessor的invoke()來實現的。每個java方法只有一個Method物件作為root,同樣,對應的methodAccessor物件也只能是一個。我們每次建立返回的Method物件都是包裝了root的物件。