首页 > Python基础教程 >
-
C# AOP学习笔记
一、AOP概念
官方解释:AOP(Aspect-Oriented Programming,面向切面编程),它是可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。它是一种新的方法论,是对传统OOP编程的一种补充。OOP是关注将需求功能划分为不同的并且相对独立、封装良好的类,并让它们有着属于自己的行为,依靠继承和多态等来定义彼此的关系;AOP是希望能够将通用需求功能从不相关的类当中分离出来,能够使得很多类共享一个行为,一旦发生变化,不必修改很多类,而只需要修改这个行为即可。AOP是使用切面(aspect)将横切关注点模块化,OOP是使用类将状态和行为模块化。在OOP的世界中,程序都是通过类和接口组织的,使用它们实现程序的核心业务逻辑是十分合适,但是对于实现横切关注点(跨越应用程序多个模块的功能需求)则十分吃力,比如日志记录、权限验证、异常拦截等。
个人理解:AOP就是将公用功能提取出来,如果以后公用功能的需求发生变化,只需要改动公用模块的代码即可,多个调用的地方则不需要改动。所谓面向切面,就是只关注通用功能,而不关注业务逻辑。它实现的方式一般是通过拦截,比如,项目中一般都有权限验证的功能,进入每个页面前都会验证当前登录用户是否有权限查看该界面。我们不可能说在每个页面的初始化方法里面都去写这段验证的代码,这个时候我们的AOP就派上用场了。AOP的机制是预先定义一组特性,使它具有拦截方法的功能,可以让你在执行方法之前和之后做你想做的业务,而我们使用的时候只需要在对应的方法或者类定义上面加上某一个特性就好了。
二、AOP优势
1)将通用功能从业务逻辑中抽离出来,可以省略大量的重复代码,有利于代码的操作和维护。
2)在软件设计时,抽出通用功能(切面),有利于软件设计的模块化,降低软件架构的复杂度。也就是说通用的功能都是一个个单独的模块,在项目的主业务里面是看不到这些通用功能的设计代码的。
三、AOP应用
3.1、静态代理方式
3.1.1、使用装饰器模式实现静态代理
1)新建一个类:DecoratorAOP.cs
/// <summary> /// 使用装饰器模式实现静态代理 /// </summary> public class DecoratorAOP { /// <summary> /// 用户类 /// </summary> public class User { public int Id { get; set; } public string Name { get; set; } public string Password { get; set; } } /// <summary> /// 用户注册接口 /// </summary> public interface IUserProcessor { void RegUser(User user); } /// <summary> /// 用户注册接口实现类 /// </summary> public class UserProcessor : IUserProcessor { public void RegUser(User user) { Console.WriteLine($"用户注册成功。Name:{user.Name} Password:{user.Password}"); } } /// <summary> /// 装饰器模式实现AOP功能 /// </summary> public class UserProcessorDecorator : IUserProcessor { private IUserProcessor UserProcessor { get; set; } public UserProcessorDecorator(IUserProcessor userProcessor) { UserProcessor = userProcessor; } public void RegUser(User user) { PreProceed(user); UserProcessor.RegUser(user); PostProceed(user); } public void PreProceed(User user) { Console.WriteLine("方法执行前"); } public void PostProceed(User user) { Console.WriteLine("方法执行后"); } } /// <summary> /// 运行测试 /// </summary> public static void Show() { User user = new User() { Name = "Hello", Password = "World" }; IUserProcessor processor = new UserProcessorDecorator(new UserProcessor()); processor.RegUser(user); } }
2)调用:
static void Main(string[] args) { #region 使用装饰器模式实现静态代理 DecoratorAOP.Show(); Console.Read(); #endregion }
3)运行结果如下:
上面代码是模拟用户注册的例子:注册信息提交前,需要做一些准备工作,比如数据有效性校验等;注册信息提交后,还需要做日志记录等。从上面的代码可以看出,我们通过静态植入的方式,手动地在执行方法前和执行方法后让它做一些我们需要的功能。
3.1.2、使用代理模式实现静态代理
1)新建一个类:ProxyAOP.cs
/// <summary> /// 使用代理模式实现静态代理 /// </summary> public class ProxyAOP { /// <summary> /// 用户类 /// </summary> public class User { public int Id { get; set; } public string Name { get; set; } public string Password { get; set; } } /// <summary> /// 用户注册接口 /// </summary> public interface IUserProcessor { void RegUser(User user); } /// <summary> /// 用户注册接口实现类 /// </summary> public class UserProcessor : IUserProcessor { public void RegUser(User user) { Console.WriteLine($"用户注册成功。Name:{user.Name} Password:{user.Password}"); } } /// <summary> /// 代理模式实现AOP功能 /// </summary> public class UserProcessorProxy : IUserProcessor { private IUserProcessor userProcessor = new UserProcessor(); public void RegUser(User user) { PreProceed(user); userProcessor.RegUser(user); PostProceed(user); } private void PreProceed(User user) { Console.WriteLine("方法执行前"); } private void PostProceed(User user) { Console.WriteLine("方法执行后"); } } public static void Show() { User user = new User() { Name = "Hello", Password = "World" }; IUserProcessor processor = new UserProcessorProxy(); processor.RegUser(user); } }
2)调用:
static void Main(string[] args) { #region 使用代理模式实现静态代理 ProxyAOP.Show(); Console.Read(); #endregion }
3)运行结果如下:
3.2、动态代理方式
3.2.1、使用.Net Remoting/RealProxy实现动态代理
1)新建一个类:RealProxyAOP.cs
/// <summary> /// 使用.Net Remoting/RealProxy实现动态代理 /// Client - TransparentProxy - RealProxy - Target Object /// 局限在业务类必须是继承自MarshalByRefObject类型 /// </summary> public class RealProxyAOP { /// <summary> /// 用户类 /// </summary> public class User { public int Id { get; set; } public string Name { get; set; } public string Password { get; set; } } /// <summary> /// 用户注册接口 /// </summary> public interface IUserProcessor { void RegUser(User user); } /// <summary> /// 用户注册接口实现类 /// 必须继承自MarshalByRefObject父类,否则无法生成。 /// </summary> public class UserProcessor : MarshalByRefObject, IUserProcessor { public void RegUser(User user) { Console.WriteLine($"用户注册成功。Name:{user.Name} Password:{user.Password}"); } } /// <summary> /// 真实代理:提供代理的基本功能 /// </summary> public class MyRealProxy<T> : RealProxy { private T _target; public MyRealProxy(T target) : base(typeof(T)) { _target = target; } public override IMessage Invoke(IMessage msg) { PreProceed(msg); IMethodCallMessage callMessage = (IMethodCallMessage)msg; object returnValue = callMessage.MethodBase.Invoke(_target, callMessage.Args); PostProceed(msg); return new ReturnMessage(returnValue, new object[0], 0, null, callMessage); } public void PreProceed(IMessage msg) { Console.WriteLine("方法执行前"); } public void PostProceed(IMessage msg) { Console.WriteLine("方法执行后"); } } /// <summary> /// 透明代理:提供实际对象驻留在客户端空间中的假象 /// </summary> public static class TransparentProxy { public static T Create<T>() { T instance = Activator.CreateInstance<T>(); MyRealProxy<T> realProxy = new MyRealProxy<T>(instance); T transparentProxy = (T)realProxy.GetTransparentProxy(); return transparentProxy; } } /// <summary> /// 运行测试 /// </summary> public static void Show() { User user = new User() { Name = "Hello", Password = "World" }; UserProcessor processor = TransparentProxy.Create<UserProcessor>(); processor.RegUser(user); } }
2)调用:
static void Main(string[] args) { #region 使用.Net Remoting/RealProxy实现动态代理 RealProxyAOP.Show(); Console.Read(); #endregion }
3)运行结果如下:
3.2.2、使用Castle\DynamicProxy实现动态代理
1)在NuGet中安装Castle.Core。
2)新建一个类:CastleProxyAOP.cs
/// <summary> /// 使用Castle\DynamicProxy实现动态代理 /// 方法必须是虚方法 /// </summary> public class CastleProxyAOP { /// <summary> /// 用户类 /// </summary> public class User { public int Id { get; set; } public string Name { get; set; } public string Password { get; set; } } /// <summary> /// 用户注册接口 /// </summary> public interface IUserProcessor { void RegUser(User user); } /// <summary> /// 用户注册接口实现类 /// </summary> public class UserProcessor : IUserProcessor { /// <summary> /// 必须带上virtual,否则无效。 /// </summary> /// <param name="user"></param> public virtual void RegUser(User user) { Console.WriteLine($"用户注册成功。Name:{user.Name} Password:{user.Password}"); } } /// <summary> /// 拦截器 /// </summary> public class MyInterceptor : IInterceptor { public void Intercept(IInvocation invocation) { PreProceed(invocation); invocation.Proceed(); PostProceed(invocation); } public void PreProceed(IInvocation invocation) { Console.WriteLine("方法执行前"); } public void PostProceed(IInvocation invocation) { Console.WriteLine("方法执行后"); } } /// <summary> /// 运行测试 /// </summary> public static void Show() { User user = new User() { Name = "Hello", Password = "World" }; ProxyGenerator generator = new ProxyGenerator(); MyInterceptor interceptor = new MyInterceptor(); UserProcessor userprocessor = generator.CreateClassProxy<UserProcessor>(interceptor); userprocessor.RegUser(user); } }
3)调用:
static void Main(string[] args) { #region 使用Castle\DynamicProxy实现动态代理 CastleProxyAOP.Show(); Console.Read(); #endregion }
4)运行结果如下:
3.2.3、使用EntLib\PIAB Unity实现AOP(非配置)
1)在NuGet中安装Unity及Unity.Interception。
2)新建一个类:UnityAOP.cs
/// <summary> /// 使用EntLib\PIAB Unity实现动态代理(非配置) /// </summary> public class UnityAOP { #region 业务 /// <summary> /// 用户类 /// </summary> public class User { public int Id { get; set; } public string Name { get; set; } public string Password { get; set; } } /// <summary> /// 用户注册接口 /// </summary> [ExceptionHandler(Order = 1)] [LogHandler(Order = 2)] [UserHandler(Order = 3)] [AfterLogHandler(Order = 5)] public interface IUserProcessor { void RegUser(User user); } /// <summary> /// 用户注册接口实现类 /// </summary> public class UserProcessor : IUserProcessor //可以不继承MarshalByRefObject类 { public void RegUser(User user) { Console.WriteLine($"用户注册成功。Name:{user.Name} Password:{user.Password}"); } } #endregion 业务 #region 特性 /// <summary> /// 异常处理特性 /// </summary> public class ExceptionHandlerAttribute : HandlerAttribute { public override ICallHandler CreateHandler(IUnityContainer container) { return new ExceptionHandler() { Order = Order }; } } /// <summary> /// 日志处理特性 /// </summary> public class LogHandlerAttribute : HandlerAttribute { public override ICallHandler CreateHandler(IUnityContainer container) { return new LogHandler() { Order = Order }; } } /// <summary> /// 用户信息特性 /// </summary> public class UserHandlerAttribute : HandlerAttribute { public override ICallHandler CreateHandler(IUnityContainer container) { ICallHandler handler = new UserHandler() { Order = Order }; return handler; } } /// <summary> /// 后续日志特性 /// </summary> public class AfterLogHandlerAttribute : HandlerAttribute { public override ICallHandler CreateHandler(IUnityContainer container) { return new AfterLogHandler() { Order = Order }; } } #endregion 特性 #region 特性对应的行为 public class ExceptionHandler : ICallHandler { public int Order { get; set; }