欢迎光临
我的个人博客网站

AOP面向切面编程(一)

本章将简单介绍下AOP面向切面编程。首先我们先来看些概念。

POP面向过程编程:符合逻辑思维,线性的处理问题—–无法应付复杂的系统。

OOP面向对象编程

  万物皆对象,对象交互完成功能,功能叠加成模块,模块组成系统,去搭建复杂的大型软件系统。

  类却是会变化的,增加日志/异常/权限/缓存/事务,只能修改类?

  只能替换整个对象,没办法把一个类动态改变。

  GOF的23种设计模式,应对变化,核心套路是依赖抽象,细节就可以变化。

AOP面向切面编程

  是一种编程思想,是OOP思想的补充。

  允许开发者动态的修改静态的OO模型,就像现实生活中对象在生命周期中会不断的改变自身。    

  正是因为能够动态的扩展功能,所以在程序设计时就可以有以下好处:

    1、只需要聚焦核心业务逻辑,权限/异常/日志/缓存/事务等通用功能可以通过AOP方式添加,使程序设计变得更加简单。

    2、功能动态扩展;集中管理;代码复用;规范化;

  实现AOP的多种方式:

    1、静态实现—装饰器模式/代理模式。

    2、动态实现—Remoting/Castle(Emit)

    3、静态织入—PostSharp(收费)—扩展编译工具,生成的加入额外代码。

    4、依赖注入容器的AOP扩展(开发)

    5、MVC的Filter—特性标记,然后该方法执行前/后就多了逻辑。

下面看一张图来辅助我们了解:

AOP面向切面编程(一)

从图中一刀切过去将核心业务逻辑和我们的通用功能分离,这样的话我们只需要聚焦核心业务逻辑,权限/异常/日志/缓存/事务等通用功能可以通过AOP方式添加,使程序设计变得更加简单。

下面我们重点来看下代码如何实现,为了演示此处我们使用VS2017建个控制台项目MyAOP,目标框架为:.NET Framework 4.6.1,如下所示:

AOP面向切面编程(一)

一、代理模式实现静态代理(静态实现AOP)

using System;  namespace MyAOP {     /// <summary>     /// 用户类     /// </summary>     public class User     {         public int Id { get; set; }         public string Name { get; set; }         public string Password { get; set; }     } }

using System;  namespace MyAOP {     /// <summary>     /// 代理模式实现静态代理     /// AOP 在方法前后增加自定义的方法     /// </summary>     public class ProxyAOP     {         public static void Show()         {             User user = new User()             {                 Name = "浪子天涯",                 Password = "123456"             };             IUserProcessor processor = new UserProcessor();             processor.RegUser(user);              Console.WriteLine("***************");              processor = new ProxyUserProcessor();             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 ProxyUserProcessor : IUserProcessor         {             private IUserProcessor _userProcessor = new UserProcessor();             public void RegUser(User user)             {                 BeforeProceed(user);                 this._userProcessor.RegUser(user);                 AfterProceed(user);             }              /// <summary>             /// 业务逻辑之前             /// </summary>             private void BeforeProceed(User user)             {                 Console.WriteLine("方法执行前");             }              /// <summary>             /// 业务逻辑之后             /// </summary>             private void AfterProceed(User user)             {                 Console.WriteLine("方法执行后");             }         }     } }

看下调用ProxyAOP.Show()的结果:

AOP面向切面编程(一)

二、装饰器模式实现静态代理(静态实现AOP)

using System;  namespace MyAOP {     /// <summary>     /// 装饰器模式实现静态代理     /// AOP 在方法前后增加自定义的方法     /// </summary>     public class DecoratorAOP     {         public static void Show()         {             User user = new User()             {                 Name = "浪子天涯",                 Password = "88888888"             };              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>             private void BeforeProceed(User user)             {                 Console.WriteLine("方法执行前");             }              /// <summary>             /// 业务逻辑之后             /// </summary>             private void AfterProceed(User user)             {                 Console.WriteLine("方法执行后");             }         }     } }

看下调用DecoratorAOP.Show()的结果:

AOP面向切面编程(一)

3、使用Unity容器实现AOP

首先来看下项目目录结构:

AOP面向切面编程(一)

需要从NuGet上引用如下程序包:

AOP面向切面编程(一)

核心业务逻辑:

using System;  namespace MyAOP.UnityWay {     public interface IUserProcessor     {         //[Obsolete] //此处可扩展         void RegUser(User user);         User GetUser(User user);     } }

using System;  namespace MyAOP.UnityWay {     public class UserProcessor : IUserProcessor     {         public void RegUser(User user)         {             Console.WriteLine("用户已注册。");         }          public User GetUser(User user)         {             return user;         }     } }

AOP扩展:

using System; using System.Collections.Generic; using Unity.Interception.InterceptionBehaviors; using Unity.Interception.PolicyInjection.Pipeline;  namespace MyAOP.UnityWay {     /// <summary>     /// 缓存AOP扩展     /// </summary>     public class CachingBehavior : IInterceptionBehavior     {         /// <summary>         /// 固定写法         /// </summary>         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);         }          /// <summary>         /// 固定写法         /// </summary>         public bool WillExecute         {             get { return true; }         }     } }

using System; using System.Collections.Generic; using Unity.Interception.InterceptionBehaviors; using Unity.Interception.PolicyInjection.Pipeline;  namespace MyAOP.UnityWay {     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; }         }     } }

using System; using System.Collections.Generic; using Unity.Interception.InterceptionBehaviors; using Unity.Interception.PolicyInjection.Pipeline;  namespace MyAOP.UnityWay {     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; }         }     } }

using System; using System.Collections.Generic; using Unity.Interception.InterceptionBehaviors; using Unity.Interception.PolicyInjection.Pipeline;  namespace MyAOP.UnityWay {     /// <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; }         }     } }

using System; using System.Collections.Generic; using System.Diagnostics; using Unity.Interception.InterceptionBehaviors; using Unity.Interception.PolicyInjection.Pipeline;  namespace MyAOP.UnityWay {     /// <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; }         }     } }

using System; using System.Collections.Generic; using Unity.Interception.InterceptionBehaviors; using Unity.Interception.PolicyInjection.Pipeline;  namespace MyAOP.UnityWay {     public class ParameterCheckBehavior : IInterceptionBehavior     {         public IEnumerable<Type> GetRequiredInterfaces()         {             return Type.EmptyTypes;         }          public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)         {             Console.WriteLine("ParameterCheckBehavior");             User user = input.Inputs[0] as User;             if (user.Password.Length < 10)             {                 return input.CreateExceptionMethodReturn(new Exception("密码长度不能小于10位"));             }             else             {                 Console.WriteLine("参数检测无误");                 return getNext().Invoke(input, getNext);             }         }          public bool WillExecute         {             get { return true; }         }     } }

Unity.config配置文件:

<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>

注意:编译时需要将配置文件输出到bin/debug目录下,设置如下所示:

AOP面向切面编程(一)

使用如下:

using System; using System.IO; using System.Configuration; using Microsoft.Practices.Unity.Configuration; using Unity;  namespace MyAOP.UnityWay {     public class UnityConfigAOP     {         public static void Show()         {             User user = new User()             {                 Name = "浪子天涯",                 Password = "12345678910"             };             //配置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);         }     } }

调用UnityConfigAOP.Show()的结果如下:

AOP面向切面编程(一)

 

Demo源码:

链接:https://pan.baidu.com/s/147Veb1fU49sT5bcEbgrERw  提取码:j5ml

此文由博主精心撰写转载请保留此原文链接:https://www.cnblogs.com/xyh9039/p/13532063.html    

版权声明:如有雷同纯属巧合,如有侵权请及时联系本人修改,谢谢!!!

赞(0) 打赏
未经允许不得转载:张拓的天空 » AOP面向切面编程(一)
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

专业的IT技术经验分享 更专业 更方便

联系我们本站主机

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏