面向切面对象AOP

前言

  面向切面编程(思想)AOP Aspect Oriented  Programming,是面向对象基础上 更关注最终目标 而不关注中间的小目标,简而言之,就是我们的目标(例如constroller)触发了我们关注的方法,此时就执行我们的观察者行为,例如在目标的方法触发前做事,触发后做事等等。

  为了让大家更好的理解,这里把面向过程、面向对象先讲解一遍。

面向过程编程(思想)POP

  Procedure  Oriented  Programming,面向过程编程思想(关注事情步骤,事情本身),将一件事情的整体看作是一个流程,我们更关注事情的流程、步骤。比如我去超市买菜,我要下楼,等红绿灯,走过几条街道,进入超市选择自己要的菜,然后排队买单。我会关注这些过程要经历的事件,步骤。

面向对象编程(思想)OOP

  Object  Oriented  Programming,面向对象编程思想(关注中间有几个对象参与其中),将原有整体事情的步骤,拆分成小段,每一个小段封装成一个单独的事情(方法),不同的方法交给不同的人来做,例如我去超市买菜,我在家里出发,最终目的是在超市买菜,中间几个环节交给不同的人(对象)来帮我做:下楼(被人背下去),打车,选菜,排队等等都有人帮我做,我只要把这些顺序连起来,指挥不同的对象按照我要求的顺序执行便可。

面向切面编程(思想)AOP

  Aspect Oriented  Programming,面向切面编程思想(面向对象基础上 更关注最终目标 而不关注中间的小目标),但要注意切面本身也是对象,比如我去超市买菜,我为起始对象,超市为目标对象,在我到超市之前所经历的事情都归纳到切面对象(下楼,打车,选菜,排队执行这些方法的人(对象)等等),连接点(管理切面对象中的方法按顺序执行),代理对象负责管理这些切面对象,切点为买菜(即在目标对象中触发我们关心的方法);

案例

  这里就用js模拟了,js模拟简单些,java模拟的话思路也是一样的,而且java的spring本身用xml或注解就可以了,这里主要讲思想

// 面向对象的方式
let money = 100;

class PersonA{
  static before(){
    console.log("走路去超市买菜");
  }
}

class My{
  static buy(){
    money -= 55;
    console.log("买完菜,减去55元");
  }
}

class PersonC{
  static after(){
    console.log("走路回家");
  }
}

PersonA.before();//走路去超市买菜
My.buy();//买完菜,减去55元
PersonC.after();//走路回家
// 面向切面的方式
class agency{//可以理解为过滤器

  before(){
    console.log("走路去超市");
  }
  
  buy(Func,spend){//代理对象
    this.before();
    Func(spend);
    this.after();
  }
  
  after(){
    console.log("走路回家");
  }

}

let agencyObj = new agency();//找代理,类似找人帮我们买菜送上门,这方式好处在于其他人还可以找代理买家具,买学习用品等等,我们生成了一次代理,然后传不同的任务进去让代理帮我们执行

class Myself{

  buy(agency,spend){
    agencyObj.buy(agency,spend);//代理对象帮我们执行的买菜方法
  }
}

let my = new Myself(10000);//实例化自己
//制定所要做的第一件事
function buy(spend) {
  money -= spend;
  console.log("买完菜,减去"+spend+"元,还剩:"+money+"元");
}
my.buy(buy,55);//这里我们以为还是自己调用方法去买菜,实际底层是代理对象帮我们执行的买菜方法


money = 1000;
//制定所要做的第二件事
function buy2(spend) {
  money -= spend;
  console.log("买完日用品,减去"+spend+"元,还剩:"+money+"元");
}
my.buy(buy2,198);
//可以看到,每次我们只需要把最终要实现的功能交给代理,最终代理对象返回想要的结果给我们

// 执行结果:
//   走路去超市
//   买完菜,减去55元,还剩:45元
//   走路回家

//   走路去超市
//   买完日用品,减去198元,还剩:802元
//   走路回家

  上面的before和after方法可以当成过滤器,比如我要得到的数据渲染前先解密,解密渲染后,部分数据用*替换这类场景。

稍微复杂一点的使用方式

  设置前置方法--before,后置方法--after-returning,异常处理--after-throwing,最终执行--after,环绕--around;

  前置方法是在目标方法前执行,后置方法在目标方法之后执行,异常处理即处理异常事件,最终执行即不管发生什么都一定会触发的事件,环绕即在目标方法触发时先后执行的事件,类似前置方法加后置方法。

案例:

// 面向切面的方式
class agency{//可以理解为过滤器

  beforeMethod(){
    console.log("走路去超市");
  }
  
  buy(Func,spend){//代理对象
    try{
      // 前置
      this.beforeMethod();
      // 环绕前
      // 目标方法(环绕的是目标的前后)
      // Func(spend);
      this.aroundMethod(Func,spend);
      // 环绕后
      // 后置
      this.afterReturningMethod();
    }catch(e){
      // 异常
      this.afterThrowingMethod();
    }finally{
      // 最终
      this.afterMethod();
    }
  }
  
  afterReturningMethod(){
    console.log("走路回家");
  }

  afterThrowingMethod(){
    console.log("代购有事,此单取消");
  }

  afterMethod(){
    console.log("谢谢您,辛苦啦");
  }

  aroundMethod(Func,spend){
    console.log("上电梯");
    Func(spend);
    console.log("下电梯");
  }

}

let agencyObj = new agency();//找代理,类似找人帮我们买菜送上门,这方式好处在于其他人还可以找代理买家具,买学习用品等等,我们生成了一次代理,然后传不同的任务进去让代理帮我们执行

class Myself{

  buy(agency,spend){
    agencyObj.buy(agency,spend);//代理对象帮我们执行的买菜方法
  }
}

let my = new Myself(10000);//实例化自己
//制定所要做的第一件事
function buy(spend) {
  money -= spend;
  console.log("买完菜,减去"+spend+"元,还剩:"+money+"元");
}
my.buy(buy,55);//这里我们以为还是自己调用方法去买菜,实际底层是代理对象帮我们执行的买菜方法


money = 1000;
//制定所要做的第二件事
function buy2(spend) {
  money -= spend;
  console.log("买完日用品,减去"+spend+"元,还剩:"+money+"元");
}
my.buy(buy2,198);
//可以看到,每次我们只需要把最终要实现的功能交给代理,最终代理对象返回想要的结果给我们

// 执行结果:
  // 走路去超市
  // 上电梯
  // 买完菜,减去55元,还剩:45元
  // 下电梯
  // 走路回家
  // 谢谢您,辛苦啦

  // 走路去超市
  // 上电梯
  // 买完日用品,减去198元,还剩:802元
  // 下电梯
  // 走路回家
  // 谢谢您,辛苦啦

  这里也可以设置为前置方法和后置方法为默认,其他方法体根据我们传入的参数值的不同(例如数字)来判断执行哪些方法,就是约定优于配置,大家约定俗成,会更有效率。

思路

  面向切面的方式就是更注重结果而不注重中间实现的步骤,中间无论由多少个切面对象帮你做了事,都由一个代理对象来帮你管理执行,而我们需要做的就是把要做的事告诉代理对象。当然面向切面的方式是否使用要根据业务场景来定,如果发现有多个方法中间需要执行的步骤流程一致,而这些方法只需要拿到经过这些步骤之后所得到的结果,不关心中间发生了什么,就使用面向切面的方式。

原文地址:https://www.cnblogs.com/zxd66666/p/13227403.html