如何自定義中介軟體,實現業務程式碼無侵入監控及攔截

打滾的豬發表於2020-09-23

 

 定義


  先看看某度某科怎麼定義的 在軟體業,AOP為Aspect Oriented Programming的縮寫,意為:面向切面程式設計,通過預編譯方式和執行期間動態代理實現程式功能的統一維護的一種技術。AOP是OOP的延續,是軟體開發中的一個熱點,也是Spring框架中的一個重要內容,是函數語言程式設計的一種衍生範型。利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率。

 

  人話就是,在進入你的業務邏輯程式碼之前,先執行一些方法操作,或者業務方法執行之後,繼續執行一些操作方法,可以用來做什麼呢 
 

  • 你想給你的網站加上鑑權,
  • 對某些url,你認為不需要鑑權就可以訪問,
  • 對於某些url,你認為需要有特定許可權的使用者才能訪問
  • 對於某些業務方法,我想監控呼叫頻率,執行效能
  • 還有騷操作的一種。收集使用者經常訪問的模組,搜尋關鍵字,喜歡看什麼,使用習慣,(看到這裡,笑容漸漸邪惡啊)提供模型給我們的演算法和機器學習,用來優化我們的推薦機制,沒錯,就是你在一個網頁裡搜尋了東西,其他的app或者網頁,會推送相關的廣告給你(誒,有意思了啊)  

      

 

 總結


 

 個人理解其實AOP像OOP一樣,只是一種程式設計正規化,AOP並沒有規定說,實現AOP協議的程式碼,要用什麼方式去實現,只要達到對業務程式碼無侵入,就可以說是AOP
 
 
 
Demo

 

  閒言少敘,程式碼見,先安裝nuget包
  Castle.Core 、 Autofac 、 Autofac.Extras.DynamicProxy
 
  這裡先預設各位同學都會用autofac,不會也沒關係,這個是完整的程式碼連結 
  
  先定義最核心的中介軟體ServiceAOP類,繼承 IInterceptor 介面  , 有兩種方式實現aop攔截
      
  public class ServiceAOP: IInterceptor
    {
        public void Intercept(IInvocation invocation)
        {
            DoSomething();
             Console.WriteLine("我要收集請求引數,發給我們演算法模型同學 \"{0}\"  引數是 {1}... ", invocation.Method.Name,   string.Join(", ", invocation.Arguments.Select(a => (a ?? "").ToString()).ToArray()));
            //執行真實業務方法
            invocation.Proceed();
        }

        public void DoSomething()
        {
            Console.WriteLine("AOP,我先說話,你們service稍後再發言!");
        }
    }

 

 

第一種

  註冊自定義的aop攔截中介軟體

 builder.RegisterType<ServiceAOP>().As<IInterceptor>().InstancePerDependency();
  註冊業務介面方法的同時 注入aop攔截中介軟體
 //第一種方式
builder.RegisterType<TestServiceTwo>().As<ITestServiceTwo>().InterceptedBy(typeof(IInterceptor)) .InstancePerDependency().EnableClassInterceptors();

 

 

第二種

 
  還是先註冊自定義的aop攔截中介軟體
  
builder.Register(c => new ServiceAOP())

 

  再在需要攔截的程式集上注入aop攔截中介軟體,
var serviceAsm = Assembly.Load(new AssemblyName("Sharper.Core"));
            builder.RegisterAssemblyTypes(serviceAsm)
                       .Where(t => typeof(ITagService).IsAssignableFrom(t) && !t.GetTypeInfo().IsAbstract)
                       .AsImplementedInterfaces()
                       .InstancePerLifetimeScope()
                       .EnableInterfaceInterceptors(); //注入攔截器

 

  註冊程式集下所有繼承ITagService的介面,並注入攔截中介軟體

  最後在需要攔截的實現類上,直接通過打標籤的形式,即可實現攔截效果

[Intercept(typeof(ServiceAOP))]
    public class TestServiceOne : ITestServiceTwo
    {
        public async Task FirstMethod()
        {
            //doSomething 業務邏輯
            await Task.Run(() =>
            {
                Console.WriteLine($"業務方法:TestServiceTwo.FirstMethod()執行成功...");
            });
        }
    }

 

 

  這樣,在執行ITestServiceTwo 介面的業務方法之前,都會先執行aop中介軟體的方法操作

 


 
  有些同學想問,你這是業務介面方法,我們想攔擊ApiController控制器的請求,怎麼處理呀,別急,這就來
 
  .net core web專案,可以對ApiController 控制器和業務方法 分別進行攔截,互不影響

  public class RequestCultureMiddleware
    {
        //定義私有隻讀的委託 RequestDelegate
        private readonly RequestDelegate _next;

        public RequestCultureMiddleware(RequestDelegate next)
        {
            _next = next;
        }
        //定義名為Invoke 或 InvokeAsync 的方法,引數為HttpContext 
        public async Task InvokeAsync(HttpContext context)
        {
            Console.WriteLine($"api 請求進來了,action{context.Request.Path}");
            // Call the next delegate/middleware in the pipeline
            await _next(context);
        }
    }
這個是微軟提供的,專門用於攔截http請求的中介軟體的元件,正好用於控制器攔截
在 Startup 的Configure 方法注入 使用中介軟體 app.UseMiddleware<RequestCultureMiddleware>();

 

這個就是本文好說的內容,其實aop中介軟體的玩法有很多,不止於上面說的哪幾種,好可以,實現快取攔截,不同的業務方法 分別進行不同資料庫初始化,同學們可以探索一下新玩法,個人感覺,這個對專案的完整性和效率幫助還是挺大的。

 

 

 

歡迎各位轉載,轉載文章必須在文章頁面明顯位置給出作者和原文連線,否則保留追究法律責任的權利。

 

 
 

 

 

相關文章