最開始接觸AOP這個概念,是在大學Java課程中(具體哪本忘記了,JavaWeb?)接觸到的。當時的理解就是,一個請求過來,自上而下,突然從中間切一刀。從那個圖是這樣理解的,文字描述的都忘記了。關於AOP的博客有好多,在工作中需要用到,我也是看著博客,外加視頻學習來理解的。 http://wayfa ...
最開始接觸AOP這個概念,是在大學Java課程中(具體哪本忘記了,JavaWeb?)接觸到的。當時的理解就是,一個請求過來,自上而下,突然從中間切一刀。從那個圖是這樣理解的,文字描述的都忘記了。關於AOP的博客有好多,在工作中需要用到,我也是看著博客,外加視頻學習來理解的。
http://wayfarer.cnblogs.com/articles/241012.html
這篇博客,寫的還是蠻詳細的。下麵只是我自己的總結。
AOP不是一種設計模式,而是一種編程思想,和POP,OOP一樣,是OOP的擴展,AOP的出現並不能代替OOP。
POP,面向過程編程:
符合邏輯思維,線性的處理問題,但是無法應對複雜的系統
OOP面向對象編程:
萬物皆對象,對象交互完成功能,功能疊加成模塊,模塊組成系統,才有機會搭建複雜的大型的軟體系統。
下麵以一個例子來作為對比:
磚塊--------牆---------房間---------大廈
類--------功能點------模塊---------系統
磚塊應該是穩定的,說明是靜態,不變的。在程式開發的過程中,類確實會變化的,增加日誌/異常/許可權/緩存/事務等,只能修改類。
在GOF23種設計模式,應對變化的,核心套路是依賴抽象,細節就可以變化,但是只能替換整個對象,沒辦法把一個類動態改變。
AOP面向切麵編程:
允許開發者動態的修改靜態的OO模型,就像現實生活中對象在生命周期中會不斷的改變自身。AOP是一種編程思想,是OOP思想的補充。
正式因為能夠動態的擴展功能,所以在程式設計的時候,就可以有以下好處:
1、聚焦核心業務邏輯,許可權/異常/緩存/事務,通過功能可以通過AOP方式添加,程式設計簡單。
2、動態擴展,集中管理,代碼復用,規範化。
下麵,用裝飾器模式,去實現一個AOP功能:
/// <summary> /// 裝飾器模式實現靜態代理 /// AOP 在方法前後增加自定義的方法 /// </summary> public class DecoratorAOP { public static void Show() { User user = new User() { Name = "bingle", Password = "123123123123" }; IUserProcessor processor = new UserProcessor(); processor.RegUser(user); Console.WriteLine("***************"); processor = new UserProcessorDecorator(processor); processor.RegUser(user); } public interface IUserProcessor { void RegUser(User user); } public class UserProcessor : IUserProcessor { public void RegUser(User user) { Console.WriteLine("用戶已註冊。Name:{0},PassWord:{1}", user.Name, user.Password); } } /// <summary> /// 裝飾器的模式去提供一個AOP功能 /// </summary> public class UserProcessorDecorator : IUserProcessor { private IUserProcessor _UserProcessor { get; set; } public UserProcessorDecorator(IUserProcessor userprocessor) { this._UserProcessor = userprocessor; } public void RegUser(User user) { BeforeProceed(user); this._UserProcessor.RegUser(user); AfterProceed(user); } /// <summary> /// 業務邏輯之前 /// </summary> /// <param name="user"></param> private void BeforeProceed(User user) { Console.WriteLine("方法執行前"); } /// <summary> /// 業務邏輯之後 /// </summary> /// <param name="user"></param> private void AfterProceed(User user) { Console.WriteLine("方法執行後"); } } }View Code
實現AOP的多種方式:
1、靜態實現----裝飾器/代理模式
2、動態實現----Remoting/Castlet
3、靜態植入---PostSharp(收費)----擴展編譯工具,生成的加入額外代碼
4、依賴註入容器的AOP擴展(Unity)
5、MVC的Filter---特性標機,然後該方法執行前後就多了邏輯
之前看到有的人認為,在.NET Core中的中間件,也是AOP的一種實現。也有一些人認為不是。博主認為,.NET Core中的中間件並不是AOP的一種實現。等後續隨筆記載到中間件的時候,再去詳細說明吧。
依賴註入容器的AOP擴展(擴展)
基於配置文件的Unity。
首先,用Nuget引入Unity想換的程式集
下麵是配置文件:
<configuration> <configSections> <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/> <!--Microsoft.Practices.Unity.Configuration.UnityConfigurationSection--> </configSections> <unity> <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration"/> <containers> <container name="aopContainer"> <extension type="Interception"/> <register type="MyAOP.UnityWay.IUserProcessor,MyAOP" mapTo="MyAOP.UnityWay.UserProcessor,MyAOP"> <interceptor type="InterfaceInterceptor"/> <interceptionBehavior type="MyAOP.UnityWay.MonitorBehavior, MyAOP"/> <interceptionBehavior type="MyAOP.UnityWay.LogBeforeBehavior, MyAOP"/> <interceptionBehavior type="MyAOP.UnityWay.ParameterCheckBehavior, MyAOP"/> <interceptionBehavior type="MyAOP.UnityWay.CachingBehavior, MyAOP"/> <interceptionBehavior type="MyAOP.UnityWay.ExceptionLoggingBehavior, MyAOP"/> <interceptionBehavior type="MyAOP.UnityWay.LogAfterBehavior, MyAOP"/> </register> </container> </containers> </unity> </configuration>View Code
使用EntLib\PIAB Unity 實現動態代理:
public class UnityConfigAOP { [Obsolete] public static void Show() { User user = new User() { Name = "bingle", Password = "1234567890123456789" }; //配置UnityContainer IUnityContainer container = new UnityContainer(); ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap(); fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\Unity.Config"); Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None); UnityConfigurationSection configSection = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName); configSection.Configure(container, "aopContainer"); IUserProcessor processor = container.Resolve<IUserProcessor>(); processor.RegUser(user); processor.GetUser(user); } }View Code
public class LogAfterBehavior : IInterceptionBehavior { public IEnumerable<Type> GetRequiredInterfaces() { return Type.EmptyTypes; } public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) { Console.WriteLine("LogAfterBehavior"); foreach (var item in input.Inputs) { Console.WriteLine(item.ToString());//反射獲取更多信息 } IMethodReturn methodReturn = getNext()(input, getNext); Console.WriteLine("LogAfterBehavior" + methodReturn.ReturnValue); return methodReturn; } public bool WillExecute { get { return true; } } }View Code
/// <summary> /// 不需要特性 /// </summary> public class LogBeforeBehavior : IInterceptionBehavior { public IEnumerable<Type> GetRequiredInterfaces() { return Type.EmptyTypes; } public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) { Console.WriteLine("LogBeforeBehavior"); foreach (var item in input.Inputs) { Console.WriteLine(item.ToString());//反射獲取更多信息 } return getNext().Invoke(input, getNext); } public bool WillExecute { get { return true; } } }View Code
public class ExceptionLoggingBehavior : IInterceptionBehavior { public IEnumerable<Type> GetRequiredInterfaces() { return Type.EmptyTypes; } public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) { Console.WriteLine("ExceptionLoggingBehavior"); IMethodReturn methodReturn = getNext()(input, getNext); if (methodReturn.Exception == null) { Console.WriteLine("無異常"); } else { Console.WriteLine($"異常:{methodReturn.Exception.Message}"); } return methodReturn; } public bool WillExecute { get { return true; } } }View Code
/// <summary> /// 不需要特性 /// </summary> public class CachingBehavior : IInterceptionBehavior { public IEnumerable<Type> GetRequiredInterfaces() { return Type.EmptyTypes; } public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) { Console.WriteLine("CachingBehavior"); //input.Target.GetType().GetCustomAttributes() if (input.MethodBase.Name.Equals("GetUser")) return input.CreateMethodReturn(new User() { Id = 234, Name = "Eleven" }); return getNext().Invoke(input, getNext); } public bool WillExecute { get { return true; } } }View Code
/// <summary> /// 性能監控的AOP擴展 /// </summary> public class MonitorBehavior : IInterceptionBehavior { public IEnumerable<Type> GetRequiredInterfaces() { return Type.EmptyTypes; } public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) { Console.WriteLine(this.GetType().Name); string methodName = input.MethodBase.Name; Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); var methodReturn = getNext().Invoke(input, getNext);//後續邏輯執行 stopwatch.Stop(); Console.WriteLine($"{this.GetType().Name}統計方法{methodName}執行耗時{stopwatch.ElapsedMilliseconds}ms"); return methodReturn; } public bool WillExecute { get { return true; } } }View Code