【Autofac打標籤模式】Aspect攔截器
- 2019 年 10 月 27 日
- 筆記
【 Autofac打標籤模式】開源DI框架擴展地址:
https://github.com/yuzd/Autofac.Annotation/wiki
前提條件
自己new一個對象不能實現攔截器功能,必須得從DI容器拿到的對象才能具備攔截器功能 可以參考 我寫的文章介紹
攔截器原理簡單介紹
用了Castle.Core組件 把你想要實現攔截器的目標類生成一個代理類。 然後織入攔截器,有2種方式
- class + 方法為virtual的方式
- 這種方式需要 從容器中是根據一個classType來獲取到目標實例
- interface + 方法重寫的方式
- 這種方式需要 從容器中是根據一個interfaceType來獲取到目標實例
攔截器開關
在你想要實現攔截的目標類上打上 【Aspect】標籤,如上面的解釋,Aspect標籤可以根據InterceptorType屬性值設定你是哪種方式的攔截器
InterceptorType屬性 | 解釋 |
---|---|
Class | 使用class的虛方法模式 【默認方式】 |
Interface | 使用介面模式 |
目的是打個標籤就能夠攔截目標方法
使得我們自定義的方法能夠
- 在指定的目標方法執行之前先執行(比如參數校驗)
- 或者在指定的目標方法執行之後執行(比如說檢驗返回值,或其他收尾工作)
- 或者環繞目標的方法,比如事務:TransactionScope或者記錄方法執行的時間
攔截器標籤 | 攔截器類型 | 使用說明 |
---|---|---|
AspectBeforeAttribute(抽象標籤類) | 前置攔截器 | 重寫Before方法 |
AspectAfterAttribute(抽象標籤類) | 後置攔截器 | 重寫After方法 |
AspectAroundAttribute(抽象標籤類) | 前置+後置攔截器 | 重寫Before和重寫After方法 |
PointcutAttribute(抽象標籤類) | 環繞攔截器 | 重寫OnInvocation方法 |
攔截器的方法參數 AspectContext 屬性說明
名稱 | 說明 |
---|---|
ComponentContext | DI容器,可以從中取得你已註冊的實例 |
InvocationContext | 執行上下文,例如被攔截的MethodInfo ,Name, Parameters,ReturnType等 |
Exception | 異常資訊,這個在前置攔截器是肯定為null,在後置攔截器中如果被攔截的方法出現了異常就能通過這個欄位拿到異常資訊 |
Exception說明
前置攔截器若拋了沒有被catch住的異常
- 如果有後置攔截器,可以在AspectContext的Exception欄位獲取。
- 如果沒有後置攔截器則拋出
前置攔截器
- 首先要自己寫一個類繼承 前置攔截器AspectBeforeAttribute(抽象標籤類)
- 實現該抽象類的Before方法
1. 然後在被攔截方法的所在類上打上 【Aspect】標籤;
2. 被攔截方法上打上 【TestHelloBefor】標籤
3. 被攔截方法需要有 virtual 關鍵字
前置攔截器方法的執行順序為:先執行 TestHelloBefor的Before方法再執行你的Say方法
後置攔截器
- 首先要自己寫一個類繼承後置攔截器AspectAfterAttribute(抽象標籤類)
- 實現該抽象類的After方法
1. 然後在被攔截方法的所在類上打上 【Aspect】標籤;
2. 被攔截方法上打上 【TestHelloAfter】標籤
3. 被攔截方法需要有 virtual 關鍵字
後置攔截器方法的執行順序為:先執行你的SayAfter方法再執行 TestHelloAfter的After方法
前置+後置攔截器
- 首先要自己寫一個類繼承攔截器AspectAroundAttribute(抽象標籤類)
- 實現該抽象類的Before 和 After方法
1. 然後在被攔截方法的所在類上打上 【Aspect】標籤;
2. 被攔截方法上打上 【TestHelloArround】標籤
3. 被攔截方法需要有 virtual 關鍵字
方法的執行順序為:
- 先執行TestHelloArround的Before方法
- 然後執行你的SayArround方法
- 再執行 先執行TestHelloArround的After方法
環繞攔截器的前置+後置的另外一種方式(更靈活)
注意:OnInvocation方法除了AspectContext參數以外 還有一個 AspectDelegate _next 參數, 如果只有一個環繞攔截器的話,那麼這個參數就是被攔截方法的本體, 如果有多個環繞攔截器的話,那麼最後一個就是被攔截方法的本體。
- 首先要自己寫一個類繼承攔截器PointcutAttribute(抽象標籤類)
- 實現該抽象類的OnInvocation方法
1. 然後在被攔截方法的所在類上打上 【Aspect】標籤;
2. 被攔截方法上打上 【TransactionInterceptor】標籤
3. 被攔截方法需要有 virtual 關鍵字
方法的執行順序為:
- 先執行TransactionInterceptor的OnInvocation方法
- 然後TransactionInterceptor的OnInvocation方法裡面執行的 await _next(aspectContext); 就會執行被攔截方法TestInterceptor;
如果有多個環繞攔截器的話,如下圖:
如上圖 程式碼的執行順序為: