天天看點

【Autofac打标簽模式】Aspect攔截器

【 Autofac打标簽模式】開源DI架構擴充位址:

https://github.com/yuzd/Autofac.Annotation/wiki

前提條件

自己new一個對象不能實作攔截器功能,必須得從DI容器拿到的對象才能具備攔截器功能 可以參考 我寫的文章介紹

攔截器原理簡單介紹

用了Castle.Core元件 把你想要實作攔截器的目标類生成一個代理類。 然後織入攔截器,有2種方式

  1. class + 方法為virtual的方式
    • 這種方式需要 從容器中是根據一個classType來擷取到目标執行個體
  2. 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字段擷取。
  • 如果沒有後置攔截器則抛出

  1. 首先要自己寫一個類繼承 前置攔截器AspectBeforeAttribute(抽象标簽類)
  2. 實作該抽象類的Before方法
【Autofac打标簽模式】Aspect攔截器

1. 然後在被攔截方法的所在類上打上 【Aspect】标簽;

2. 被攔截方法上打上 【TestHelloBefor】标簽

3. 被攔截方法需要有 virtual 關鍵字

【Autofac打标簽模式】Aspect攔截器

前置攔截器方法的執行順序為:先執行 TestHelloBefor的Before方法再執行你的Say方法

  1. 首先要自己寫一個類繼承後置攔截器AspectAfterAttribute(抽象标簽類)
  2. 實作該抽象類的After方法
【Autofac打标簽模式】Aspect攔截器

2. 被攔截方法上打上 【TestHelloAfter】标簽

【Autofac打标簽模式】Aspect攔截器

後置攔截器方法的執行順序為:先執行你的SayAfter方法再執行 TestHelloAfter的After方法

  1. 首先要自己寫一個類繼承攔截器AspectAroundAttribute(抽象标簽類)
  2. 實作該抽象類的Before 和 After方法
【Autofac打标簽模式】Aspect攔截器

2. 被攔截方法上打上 【TestHelloArround】标簽

【Autofac打标簽模式】Aspect攔截器

方法的執行順序為:

  1. 先執行TestHelloArround的Before方法
  2. 然後執行你的SayArround方法
  3. 再執行 先執行TestHelloArround的After方法

環繞攔截器的前置+後置的另外一種方式(更靈活)

注意:OnInvocation方法除了AspectContext參數以外 還有一個 AspectDelegate _next 參數, 如果隻有一個環繞攔截器的話,那麼這個參數就是被攔截方法的本體, 如果有多個環繞攔截器的話,那麼最後一個就是被攔截方法的本體。

  1. 首先要自己寫一個類繼承攔截器PointcutAttribute(抽象标簽類)
  2. 實作該抽象類的OnInvocation方法
【Autofac打标簽模式】Aspect攔截器

2. 被攔截方法上打上 【TransactionInterceptor】标簽

【Autofac打标簽模式】Aspect攔截器
  1. 先執行TransactionInterceptor的OnInvocation方法
  2. 然後TransactionInterceptor的OnInvocation方法裡面執行的 await _next(aspectContext); 就會執行被攔截方法TestInterceptor;

如果有多個環繞攔截器的話,如下圖:

【Autofac打标簽模式】Aspect攔截器
【Autofac打标簽模式】Aspect攔截器

如上圖 代碼的執行順序為:

【Autofac打标簽模式】Aspect攔截器

如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的“推薦”将是我最大的寫作動力!歡迎各位轉載,轉載文章之後須在文章頁面明顯位置給出作者和原文連接配接,謝謝。

繼續閱讀