1. 程式人生 > >【Autofac打標籤模式】Aspect攔截器

【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方法

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

2. 被攔截方法上打上 【TestHelloBefor】標籤

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

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

後置攔截器

  1. 首先要自己寫一個類繼承後置攔截器AspectAfterAttribute(抽象標籤類)
  2. 實現該抽象類的After方法

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

2. 被攔截方法上打上 【TestHelloAfter】標籤

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

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

前置+後置攔截器

  1. 首先要自己寫一個類繼承攔截器AspectAroundAttribute(抽象標籤類)
  2. 實現該抽象類的Before 和 After方法

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

2. 被攔截方法上打上 【TestHelloArround】標籤

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

方法的執行順序為:

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

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

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

  1. 首先要自己寫一個類繼承攔截器PointcutAttribute(抽象標籤類)
  2. 實現該抽象類的OnInvocation方法

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

2. 被攔截方法上打上 【TransactionInterceptor】標籤

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

方法的執行順序為:

  1. 先執行TransactionInterceptor的OnInvocation方法
  2. 然後TransactionInterceptor的OnInvocation方法裡面執行的 await _next(aspectContext); 就會執行被攔截方法TestInterceptor;

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

如上圖 程式碼的執行順序為: