zoukankan      html  css  js  c++  java
  • 面向切面编程AOP

    最开始接触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

     使用EntLibPIAB 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
  • 相关阅读:
    Vue中改变对象的注意事项
    Object.assign简单总结
    Base64编码
    vue中prop传值时加不加v-bind(冒号:)
    内联元素的padding和margin
    flex自适应宽度显示省略号
    Http和Https
    JVisualVM 模拟一次内存泄漏场景分析
    Lucene
    布隆算法原理
  • 原文地址:https://www.cnblogs.com/taotaozhuanyong/p/11552694.html
Copyright © 2011-2022 走看看