2020年8月20日星期四

AOP面向切面编程(一)

本章将主要简单介绍下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方式添加,使程序设计变得更加简单。

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

一、代理模式实现静态代理(静态实现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)

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()的结果:

3、使用Unity容器实现AOP

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

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

核心业务逻辑:

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目录下,设置如下所示:

使用如下:

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()的结果如下:

 

Demo源码:

 

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

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

AOP面向切面编程(一)东杰智能grabpatents【紧急通知】亚马逊账号需要提交多份身份资料了!如何利用亚马逊自然排名和广告排名为自己的运营加分?欧洲BAP听说泡温泉能治病,请问是不是真的?2008奥运村地址在哪里?2017年清明节可以提前多少天订票?