欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

面向切面编程AOP

程序员文章站 2022-12-22 11:35:41
最开始接触AOP这个概念,是在大学Java课程中(具体哪本忘记了,JavaWeb?)接触到的。当时的理解就是,一个请求过来,自上而下,突然从中间切一刀。从那个图是这样理解的,文字描述的都忘记了。关于AOP的博客有好多,在工作中需要用到,我也是看着博客,外加视频学习来理解的。 http://wayfa ......

最开始接触aop这个概念,是在大学java课程中(具体哪本忘记了,javaweb?)接触到的。当时的理解就是,一个请求过来,自上而下,突然从中间切一刀。从那个图是这样理解的,文字描述的都忘记了。关于aop的博客有好多,在工作中需要用到,我也是看着博客,外加视频学习来理解的。

这篇博客,写的还是蛮详细的。下面只是我自己的总结。

aop不是一种设计模式,而是一种编程思想,和pop,oop一样,是oop的扩展,aop的出现并不能代替oop。

pop,面向过程编程:

  符合逻辑思维,线性的处理问题,但是无法应对复杂的系统

oop面向对象编程:

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

  下面以一个例子来作为对比:

    砖块--------墙---------房间---------大厦

    类--------功能点------模块---------系统

  砖块应该是稳定的,说明是静态,不变的。在程序开发的过程中,类确实会变化的,增加日志/异常/权限/缓存/事务等,只能修改类。

  在gof23种设计模式,应对变化的,核心套路是依赖抽象,细节就可以变化,但是只能替换整个对象,没办法把一个类动态改变。

面向切面编程AOP

 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("方法执行后");
         }
     }

 }

实现aop的多种方式:

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

  2、动态实现----remoting/castlet

  3、静态植入---postsharp(收费)----扩展编译工具,生成的加入额外代码

  4、依赖注入容器的aop扩展(unity)

  5、mvc的filter---特性标机,然后该方法执行前后就多了逻辑

  之前看到有的人认为,在.net core中的中间件,也是aop的一种实现。也有一些人认为不是。博主认为,.net core中的中间件并不是aop的一种实现。等后续随笔记载到中间件的时候,再去详细说明吧。

  依赖注入容器的aop扩展(扩展)

  基于配置文件的unity。

  首先,用nuget引入unity想换的程序集面向切面编程AOP

 

 下面是配置文件: 

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

面向切面编程AOP

 

 使用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);
     }
 }
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; }
    }
}
 /// <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; }
     }
 }
 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; }
     }
 }
/// <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; }
    }
}
/// <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; }
    }
}