JavaScript中的AOP编程的基本实现_第1页
JavaScript中的AOP编程的基本实现_第2页
JavaScript中的AOP编程的基本实现_第3页
JavaScript中的AOP编程的基本实现_第4页
JavaScript中的AOP编程的基本实现_第5页
已阅读5页,还剩1页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第JavaScript中的AOP编程的基本实现AOP简介

AOP(面向切面编程)的主要作用是把一些跟核心业务逻辑模块无关的功能抽离出来,这些跟业务逻辑无关的功能通常包括日志统计、安全控制、异常处理等。把这些功能抽离出来之后,再通过“动态织入”的方式掺入业务逻辑模块中。

面向切面编程给我们提供了一个方法,让我们可以在不修改目标逻辑的情况下,将代码注入到现有的函数或对象中。

虽然不是必须的,但注入的代码意味着具有横切关注点,比如添加日志功能、调试元数据或其它不太通用的但可以注入额外的行为,而不影响原始代码的内容。

给你举一个合适的例子,假设你已经写好了业务逻辑,但是现在你意识到没有添加日志代码。通常的方法是将日志逻辑集中到一个新的模块中,然后逐个函数添加日志信息。

然而,如果你可以获取同一个日志程序,在你想要记录的每个方法执行过程中的特定节点,只需一行代码就可将程序注入,那么这肯定会给你带来很多便利。难道不是吗?

切面、通知和切点(是什么、在何时、在何地)

为了使上面的定义更形式化一点,让我们以日志程序为例,介绍有关AOP的三个概念。如果你决定进一步研究这个范式,这些将对你有所帮助:

切面(是什么):这是你想要注入到你的目标代码的“切面”或者行为。在我们的上下文环境(JavaScript)中,这指的是封装了你想要添加的行为的函数。

通知(在何时):你希望这个切面什么时候执行?“通知”指定了你想要执行切面代码的一些常见的时刻,比如“before”、“after”、“around”、“whenThrowing”等等。反过来,它们指的是与代码执行相关的时间点。对于在代码执行后引用的部分,这个切面将拦截返回值,并可能在需要时覆盖它。

切点(在何地):他们引用了你想要注入的切面在你的目标代码中的位置。理论上,你可以明确指定在目标代码中的任何位置去执行切面代码。实际上这并不现实,但你可以潜在地指定,比如:“我的对象中的所有方法”,或者“仅仅是这一个特定方法”,或者我们甚至可以使用“所有以get_开头的方法”之类的内容。

有了这些解释,你会发现创建一个基于AOP的库来向现有的基于OOP的业务逻辑(举个例子)添加日志逻辑是相对容易的。你所要做的就是用一个自定义函数替换目标对象现有的匹配方法,该自定义函数会在适当的时间点添加切面逻辑,然后再调用原有的方法。

因为我是一个视觉学习者,所以我认为,展示一个基本的例子说明如何实现一种切面方法来添加基于AOP的行为将是个漫长的过程。

下面的示例将阐明实现它有多容易以及它给你的代码带来的好处。

`/**用于获取一个对象中所有方法的帮助函数*/constgetMethods=(obj)=Object.getOwnPropertyNames(Object.getPrototypeOf(obj)).filter(item=typeofobj[item]==='function')

/**将原始方法替换为自定义函数,该函数将在通知指示时调用我们的切面*/functionreplaceMethod(target,methodName,aspect,advice){constoriginalCode=target[methodName]target[methodName]=(...args)={if(["before","around"].includes(advice)){aspect.apply(target,args)}constreturnedValue=originalCode.apply(target,args)if(["after","around"].includes(advice)){aspect.apply(target,args)}if("afterReturning"==advice){returnaspect.apply(target,[returnedValue])}else{returnreturnedValue

}}}

module.exports={//导出的主要方法:在需要的时间和位置将切面注入目标inject:function(target,aspect,advice,pointcut,method=null){if(pointcut=="method"){if(method!=null){replaceMethod(target,method,aspect,advice)

}else{thrownewError("Tryintoaddanaspecttoamethod,butnomethodspecified")}}if(pointcut=="methods"){constmethods=getMethods(target)methods.forEach(m={replaceMethod(target,m,aspect,advice)

})}}}`

非常简单,正如我提到的,上面的代码并没有涵盖所有的用例,但是它应该足以涵盖下一个示例。

但是在我们往下看之前,注意一下这个replaceMethod函数,这就是“魔法”生效的地方。它能够创建新函数,也可以决定我们何时调用我们的切面以及如何处理它的返回值。

接下来说明这个库的用法:

`constAOP=require("./aop.js")

classMyBussinessLogic{

add(a,b){

console.log("Callingadd")

returna+b

concat(a,b){

console.log("Callingconcat")

returna+b

power(a,b){

console.log("Callingpower")

returna**b

consto=newMyBussinessLogic()

functionloggingAspect(...args){console.log("==Callingtheloggerfunction==")console.log("Argumentsreceived:"+args)}

functionprintTypeOfReturnedValueAspect(value){console.log("Returnedtype:"+typeofvalue)}

AOP.inject(o,loggingAspect,"before","methods")AOP.inject(o,printTypeOfReturnedValueAspect,"afterReturning","methods")

o.add(2,2)o.concat("hello","goodbye")o.power(2,3)`

这只是一个包含三个方法的基本对象,没什么特别的。我们想要去注入两个通用的切面,一个用于记录接收到的属性,另一个用于分析他们的返回值并记录他们的类型。两个切面,两行代码(并不需要六行代码)。

这个示例到这里就结束了,这里是你将得到的输出:

/f18ef187f4acddab8df097c8aa4521d632e17759bc1c0831a22ada934388d7b5/68747470733a2f2f63646e2d696d616765732d312e6d656469756d2e636f6d2f6d61782f323030302f312a394b5a42774f6262714145754a4176314757537279672e706e67

AOP的优点

在知道了AOP的概念及用途后,也行你已经猜到了为什么人们会想要使用面向切面编程,不过还是让我们做一个快速汇总吧:

封装横切关注点的好方法。我非常喜欢封装,因为它意味着更容易阅读和维护可以在整个项目中重复使用的代码。

灵活的逻辑。在注入切面时,围绕通知和切入点实现的逻辑可以为你提供很大的灵活性。反之这又有助于你动态地打开和关闭代码逻辑的不同切面(有意的双关)。

跨项目重复使用切面。你可以将切面视为组件,即可以在任何地方运行的小的、解耦的代码片段。如果你正确地编写了切面代码,就可以轻松地在不同的项目中共享它们。

AOP的主要问题

因为并非每件事都是完美的,这种范式遭到了一些批评者的反对。

他们提出的主要问题是,它的主要的优势实际上隐藏了代码逻辑和复杂性,在不太清楚的情况下可能会产生副作用。

如果你仔细想想,他们说的有一定道理,AOP给了你很多能力,可以将无关的行为添加到现有的方法中,甚至可以替换它们的整个逻辑。当然,这可能不是引入此范式的确切原因,而且它肯定不是我上面提供的示例的意图。

然而,它确实可以让你去做任何你想做的事情,再加上缺乏对良好编程实践的理解,可能会导致非常大的混乱。

为了不让自己听起来太老套,我转述一下UncleBen的话:

能力越大,责任越大

如果你想正确地使用AOP,那么就必须理解软件开发的最佳实践。

在我看来,仅仅因为你使用这个工具之后可能会带来很大的损害,并不足以说明这个工具就是不好的,因为它也会带来很多的好处(即你可以将很多常见的逻辑提取到一个集中的位置,并可以在你需要的任何地方用一行代码注入它)。对我来说,这是一个强大的工具,值得学习,也绝对值得使用。

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论