內容涉及:泛型、反射、註解、動態代理。
分包
annotations:用於存放註解
bean:用於存放實體類
handler:用於存放動態代理中的處理器
interfaces:用於存放動態代理中的接口
interfacesImpl:用於存放接口的實現,也就是動態代理中的被代理對象(目標對象)。
utils:用於存放工具類,也是這個框架的核心包。
annotations包
annotations存放有三個自定義註解:
@before:只能允許用來註解方法,用來標註這是一個前置通知。
@after:只能允許用來註解方法,用來標註這是一個後置通知。
@section:只允許用來註解類,用來標註這是一個切面。
utils包
框架的核心包,此包存放框架的5大組件:
scanner:掃描器,用於掃描切面並向註冊中心中登記註冊切面以及切面中的通知。
resovler:解析器,用於解析註冊中心中註冊的切面及切面中的通知。並且調用執行器來執行通知。
executor:執行器,用於執行切面中的通知。
sectionRegistry:註冊中心,用於存放切面的消息(信息就是當前切面中前置。後置通知有哪些)
bean包
bean包中存放的最重要的一個類就是regisInfo
一個regisInfo就是一個切面的詳細信息。
ClassName:切面的名字(類名)
methodsName:切面中的所有方法名
五大核心組件
前文以及說過五大核心組件的作用,現在以一個切面被掃描、註冊、解析、執行的完整流程來詳解五大核心組件間的調用關係以及各自的源代碼:
掃描
掃描由sanner(掃描器)來完成
首先是scanf方法去掃描傳入的Class對象,通過註解來判斷是否爲切面,
如果是切面就通過反射來拿到類中的所有方法,再調用scan方法繼續掃描這些方法
(這裏偷懶沒有定義異常,而是直接用的輸出,hhhh,後面升級版本的時候再改吧~狗頭)
scan方法會遍歷類中的方法,通過註解判斷方法是否是前置(後置)通知,
如果是前置(後置)通知就將其暫時存放到List中去,
掃描器中有兩個成員變量:
beforeList:存放在scan中被掃描出來的前置通知。
afterList:存放在scanf中被掃描出來的後置通知。
所有方法掃描完後調用register方法向註冊中心註冊切面和切面中的通知
註冊
掃描器的register方法其實就是通過beforeList、afterList來實例化出兩個regisInfo,然後放入註冊中心中的List去。
註冊中心:
註冊中心中有兩個List分別存放前置、後置通知。
解析
解析由resovler(解析器)來完成,
解析器的工作很簡單,就是去分別遍歷註冊中心中存放前後置通知的兩個List,
遍歷的過程中調用executor來執行通知。
執行
執行由executor來負責,
executor的工作也很簡單,通過解析器解析出來的類名、方法兩個參數加上反射來執行所有方法
切面切入
框架中使用動態代理來代理對象,切面就是在動態代理的處理器handler的核心方法invoke中切入的。
前置通知就放在method.invoke()的前面
後置通知就放在method.invoke()的後面
測試
首先準備代理對象及其接口:
準備切面:
測試方法:
(測試方法其實還有一部分功能性的方法,後期版本升級的時候會單獨再做封裝,抽出一個工具類來,最後只暴露給開發者一個藉口)