前言

本意不想用太长的篇幅,来阐述这个话题。但是有些概念和设计思路有必要讲清楚,以便于搞清楚其深层次的内在逻辑。这是我一直遵从的“知其然,知其所以然”的原则。首先,本文将简单的阐述一下概念;进而,举例一起探讨一下前端AOP实现方式,以及随着前端语言ES5、ES6、Typescript的发展,实现方式的演变;最后,一起了解一下实际项目中AOP的应用场景、相关框架以及开发模式。

什么是AOP?

AOP为Aspect Oriented Programming的缩写,意为:面向切面编程。主要意图是将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。

简而言之,就是“优雅”的把“辅助功能逻辑”从“业务逻辑”中分离解耦。

简单说一下AOP中的一些概念

确切说是其实是AspectJ中的相关概念。AspectJ是一个扩展了Java语言的面向切面的框架。其优秀的设计思想值得我们参考学习。

AspectJ的主要相关概念有下面这些:

  • 连接点(Joinpoint):表示在程序中明确定义的点,典型的包括方法调用,对类成员的访问以及异常处理程序块的执行等等
  • 切入点(Pointcut):表示一组Joinpoint,这些Joinpoint或是通过逻辑关系组合起来,或是通过通配、正则表达式等方式集中起来,它定义了将要放置增强Advice的地方。比如"所有类的submit和reset方法调用执行”
  • 切面(Aspect):由切点和增强组成,既包含了增强逻辑的具体实现和连接点的定义
  • 通知/增强(Advice):具体的增强逻辑实现。通常依据放置的地方不同,可分为前置通知(Before)、后置返回通知(AfterReturning)、后置异常通知(AfterThrowing)、后置通知(After)与围绕通知(Around)5种
  • 织入(Weaving):将切面应用到目标对象从而创建一个新的代理对象的过程

为了便于理解,我们可以把一个业务流程比作一个面包,那么面包切片就是一个业务模块或者功能。类似于“某个切面的前面”,“某个切片的后面”这种描述叫做连接点(Joinpoint);把花生酱、面包、生菜打包成一个独立模块进行逻辑处理,就是一个切面(Aspect);切面可以定义通知(Advice)、切入点(Pointcut)也即放入通知的连接点;把切面跟面包结合,从而制成三明治这个过程叫做织入(Weaving)。

早期前端AOP的简单实现

多数的前端的编程思想、设计模式、框架以及工具,都是参考服务端已经应用成熟的设计思路实现的,AOP也不例外。我们前面已经讲过一些AspectJ的相关概念。很明显,下面我们打算参照其用法,逐步实现前端AOP编程。

通过前面对AspectJ的概念的分析,可以得出一个简略的总结:AOP编程就是在不破坏原有代码的基础上,在原执行动作之前或者之后,加入一段自定义的动作。这里的“原有动作”是函数,“增强的动作”也是函数,把他们打包成一个动作也是函数。显然,基于javascript语言的特性,函数式编程是实现前端AOP编程的最佳方式。

看下面的简单实现:

/**

调用执行:

function

执行结果

这里面通过传参匹配到的"oldFn的调用执行"对应切入点(PointCut);before和after对应通知/增强(Advice);创造newFn的过程可以对应织入(Weaving)动作。另外,还可以参考AspectJ的用法,简单模拟一下每个增强对应的连接点(JoinPoint)信息。

var

测试调用:

// ......省略

执行结果

至此,已经可以初见前端AOP编程的雏形。前面例子已经简单实现过前置通知(Before)和后置终于通知(After)。还有后置返回通知(AfterReturning)、后置异常通知(AfterThrowing)、与围绕通知(Around)的具体实现没有讨论。接下来,我们将简单的模拟实现一个简单完整的AspectJS。

  • Before标识的方法为前置方法,在目标方法的执行之前执行,即在连接点之前进行执行。
  • Around环绕通知方法可以包含上面四种通知方法,环绕通知的功能最全面。且环绕通知必须有返回值, 返回值即为目标方法的返回值。对应JoinPoint需要附带可执行原执行动作的方法(invoke)

比如我们需要计算原函数的执行时间

function

  • AfterThrowing异常通知方法只在连接点方法出现异常后才会执行,否则不执行。因此对应JoinPoint需要附带异常参数(exception)
try

  • AfterReturning当连接点方法成功执行后,返回通知方法才会执行,如果连接点方法出现异常,则返回通知方法不执行。返回通知方法在目标方法执行成功后才会执行,所以,返回通知方法可以拿到目标方法(连接点方法)执行后的结果。因此对应的JoinPoint需要附带执行结果(result)
try

  • After后置通知方法在连接点方法完成之后执行,无论连接点方法执行成功还是出现异常,都将执行后置方法
// brefore

下面完整的实现一下这个简略版的AOP工具

/**

下面通过一个简单的实例简单说明。同样的,我们打算在Person类的run方法的执行前后织入增强。按照前面的实现思路:

function

这是针对单独类方法AOP的实现。显然这里面存在以下几个问题:

  • 现实中不总是针对一个应用类的一个方法做AOP处理
  • 应该如何如何定义切面Aspect,也就是上面定advices
  • 一个应用类不总是对应一个切面Aspect
  • 一个切面Aspect也不总是对应一个应用类

综上所述,更合理的应用类织入切面Aspect应该是这样的:

var

这里引发出另外一个问题,切面类Aspect应该是什么样子?应该如何定义?

前面讲过,切面包括切点(joinPoint)和通知(advice),方法名称对应切点joinPoint,相应的增强函数对应通知advice。那么一个简单的Aspect应该是这样子:

var

相应的我们创建一个织入Weaving函数

var

看一下完整的实例:

function

至此,一个简略版的前端AOP工具已经完成了。但是这里依然存在一些问题。

比如:

  • 上面讨论过的应用类和Aspect多对多关系
  • Aspect类的实现
  • ES6和Typescript的出现与发展对前端AOP开发带来哪些影响?
  • AOP的应用以及遇到的问题及其解决办法

由于篇幅所限我们将在下一篇文章继续讨论,继续完善我们上面实现的AOP工具。

这仅仅是一个开始,我们需要讨论的还有很多......

aop执行跳过某个方法_简谈前端开发中的AOP(一) -- 前端AOP的实现思路相关推荐

  1. c语言 单词变复数_简谈C语言中的复数

    C语言中的复数操作 注: complex类型是自c99标准后引入,具体实现并不是标准的,每个编译器的实现的标准可能不一样,具体的还请查询相关的编译器的实现标准. 复数在数学运算中十分重要,在编写数值运 ...

  2. java怎么设置全局变量_浅谈Java开发中如何定义的全局变量

    Static静态变量 在程序中任何变量或者代码都是在编译时,是由系统自动分配内存来存储的,而所谓静态就是指在编译后分配的内存会一直存在,直到程序退出时才会释放内存空间. static是静态修饰符.被s ...

  3. 简谈FPGA设计中不同设计方法资源消耗对比

    简谈FPGA设计中不同设计方法资源消耗对比 今天和大侠简单聊一聊FPGA设计中不同设计方法硬件资源消耗对比,话不多说,上货. 在这里,我们使用Verilog HDL 设计计数器,通过两种不同的写法,对 ...

  4. 前端开发中遇到的问题及解决方法

    前端开发中遇到的问题及解决方法 1,何为MVVM? view层: 视觉层:在前端开发中,通常是DOM层:主要作用是给用户展示各种信息: Model层: 数据层:数据可能是我们固定的死数据,更多的是来自 ...

  5. aop 获取注解注释的方法_带有AOP和注释的Java方法记录

    aop 获取注解注释的方法 有时,我想记录(通过slf4j和log4j )方法的每次执行,查看其接收的参数,返回的内容以及每次执行花费的时间. 这是我在AspectJ , jcabi-aspects和 ...

  6. python nonlocal的用法_简谈Python3关键字nonlocal使用场景

    下面是之前提过的有待提升效率的计算移动平均的方法: def make_averager(): series = [] def averager(new_value): series.append(ne ...

  7. web开发方法_确保进入Web开发的最快方法

    web开发方法 做很多项目. (Do lots of projects.) I'm not kidding, it's really that simple. If you've internaliz ...

  8. echarts setoption方法_在Vue和React中使用ECharts的多种方法

    前言 俗话说:"工欲善其事,必先利其器".现如今已经有许多成熟易用的可视化解决方案,例如ECharts,AntV等等.我们可以把这些解决方案比作是一套套成熟的"工具&qu ...

  9. 异步复位同步释放_简谈同步复位和异步复位

    简谈同步复位和异步复位 大侠们,江湖偌大,有缘相见,欢迎一叙,今天来聊一聊数字电路设计中的同步复位和异步复位. 谈到同步复位和异步复位,那咱们就不得不来聊一聊复位这个词了.在数字逻辑电路设计中,电路通 ...

最新文章

  1. 再谈应用环境下的TIME_WAIT和CLOSE_WAIT
  2. NServiceBus教程-消息传递与处理
  3. boost::hana::make_type用法的测试程序
  4. linux move权限,Red Hat Enterprise Virtualization Manager MoveDisk目标域权限检查不足拒绝服务漏洞...
  5. Java System类loadLibrary()方法与示例
  6. 参数少一半、速度快3倍:最新目标检测核心架构来了
  7. Python3环境下django连接mysql报错:No module named 'MySQLdb'
  8. 学历全靠编,融资靠忽悠?网传“包养7个女主持”的金融大佬被揭穿了
  9. XML与HTML的区别
  10. drawroundrect java_java – fillRoundRect看似无法正确呈现的问题
  11. matlab人工神经网络教程,人工神经网络作业MATLAB仿真(共3篇)
  12. kindle导出笔记html,手把手教你导出kindle笔记链接Evernote
  13. 常用 EPSG 编号对应的投影信息
  14. Educational Codeforces Round 87 (Rated for Div. 2)A. Alarm Clock
  15. Python转换excel文件,将xlsx文件转换为xls文件
  16. 阿里云Centos7安装mysql5.7
  17. SAP 玻璃原片单位问题处理
  18. 牛客每日练习----あなたの蛙が帰っています,おみやげをまらいました,写真がとどいています
  19. 平方米用计算机怎么打,平方厘米用电脑怎么打
  20. lftp下载文件无法覆盖,提示 file already existst and xfer:clobber is unset 问题解决

热门文章

  1. python基础数据类型一(元祖)
  2. Swoole-2.1.2 进程池模块的使用
  3. PHP用单例模式实现一个数据库类
  4. Bug之PHPMailer附件名字不支持中文的
  5. java session创建_request创建session
  6. mysql5.6.22.0安装_皮带机滚筒用圆锥孔调心滚子轴承锁紧安装工艺
  7. sql参数化还是被注入了_面试官问你 SQL 注入攻击了吗?
  8. 排查链接是否失效_如何进行移动站点流量排查?
  9. 学计算机cpu重要还是显卡重要,玩游戏的过程中究竟是显卡重要还是CPU重要?
  10. producer send源码_RocketMq系列之Producer顺序消息发送源码分析(四)