在軟體業,AOP為Aspect Oriented Programming的縮寫,意為:面向切麵編程,通過預編譯方式和運行期動態代理實現程式功能的統一維護的一種技術。AOP是OOP的延續,是軟體開發中的一個熱點,是函數式編程的一種衍生範型。利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各 ...
在軟體業,AOP為Aspect Oriented Programming的縮寫,意為:面向切麵編程,通過預編譯方式和運行期動態代理實現程式功能的統一維護的一種技術。AOP是OOP的延續,是軟體開發中的一個熱點,是函數式編程的一種衍生範型。利用AOP可以對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度降低,提高程式的可重用性,同時提高了開發的效率。
在.NET Core中比較好的AOP框架有一個叫做Aspect的這樣的一個框架, 它是一個國產的!如何引入AspectCore? 可以直接nuget。
這AspectCore中需要創建一個攔截器一般繼承自 AbstractInterceptorAttribute。並且實現它的 Invoke 方法 。
其中第一個參數是上下文,next是執行的委托方法,通過這個委托可以執行被攔截的方法。
//每個被攔截的方法中執行 public async override Task Invoke(AspectContext context, AspectDelegate next) { try { Console.WriteLine("Before service call"); await next(context); } catch (Exception) { Console.WriteLine("Service threw an exception!"); throw; } finally { Console.WriteLine("After service call"); } }
首先我們可以創建一個需要被代理攔截的類(必須是public方法是虛方法且被標記,也必須使用MVC中的Filter命名規範)。這個方法也可以是非同步的!
public class Person { [CustomInterceptor] public virtual void Say(string msg) { Console.WriteLine("service calling..."+msg); } }
如何進行代理? 需要通過ProxyGeneratorBuilder 來代理對象,註意 p 指向的對象是 AspectCore 生成的 Person 的動態子類的對象,直接 new Person是無法被攔截的。
static void Main(string[] args) { ProxyGeneratorBuilder proxyGeneratorBuilder = new ProxyGeneratorBuilder(); using (IProxyGenerator proxyGenerator = proxyGeneratorBuilder.Build()) { Person p = proxyGenerator.CreateClassProxy<Person>(); p.Say("zaranet"); } }
上面說到我們不可以直接new這個person,那現在我們調試一下,一探究竟!!!我們看看這個p是個什麼類型。
噫?為什麼這個p不是AspectPollyIdn.Person?而是AspectCore.DynamicGenerated.Person?不妨把這個p的父類給列印出來,來瞅瞅。
static void Main(string[] args) { ProxyGeneratorBuilder proxyGeneratorBuilder = new ProxyGeneratorBuilder(); using (IProxyGenerator proxyGenerator = proxyGeneratorBuilder.Build()) { Person p = proxyGenerator.CreateClassProxy<Person>(); Console.WriteLine(p.GetType().BaseType); p.Say("zaranet"); } }
現在的對象是我們了,也就是它的父類,那這個時候你就絕對要明白了,為什麼我們的被代理類是虛方法,也就是說它用子類類重寫了我們被代理類的虛方法,也就實現了AOP,那麼呢這也就是Aspect.Core的原理。大概簡單的就是這樣。
現在你已經瞭解了AspectCore的原理了,但回頭髮現每次來創建這些對象都非常繁瑣,我們只想去使用AspectCore通過CreateClassProxy()來創建我們想要的代理對象,那麼現在我們可以使用AspNetCore的依賴註入解決這個問題。
首先呢,我們引用AspectCore.Extensions.DependencyInjection,這是AspectCore給我們的一個DI框架。再把Startup中的ConfigureServices進行改造。
public IServiceProvider ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); services.AddSingleton<Person>(); return services.BuildAspectInjectorProvider(); }
隨便創建一個類 繼承與AbstractInterceptorAttribute ,重寫方法,再添加一個Person。
public class Person { [CustomInterceptor] public virtual void Say(string msg) { // } }
在API中重載進行依賴註入。下麵我們進行postman進行測試,因為已經關閉了瀏覽器瀏覽。
private Person p; public ValuesController(Person p) { this.p = p; }
OK,成功。