前端解读面向切面编程(AOP)
前言
面向对象(OOP)作为经典的设计范式,对于我们来说可谓无人不知,还记得我们入行起始时那句经典的总结吗-万事万物皆对象。
是的,基于OOP思想封装、继承、多态的特点,我们会自然而然的遵循模块化、组件化的思维来设计开发应用,以到达易维护、可扩展、高复用的目的。
既然OOP这么多优点,那么经常被大家提起的面向切面编程(AOP)是什么回事呢,下面我们就一起来看一下。
AOP定义
第一步还是要知道aop是什么,先个来自维基百科的解释:
面向侧面的程序设计(aspect-oriented programming,AOP,又译作面向方面的程序设计、观点导向编程、剖面导向程序设计)是计算机科学中的一个术语,指一种程序设计范型。
侧面的概念源于对面向对象的程序设计的改进,但并不只限于此,它还可以用来改进传统的函数。
其从主关注点中分离出横切关注点是面向侧面的程序设计的核心概念。分离关注点使得解决特定领域问题的代码从业务逻辑中独立出来.
业务逻辑的代码中不再含有针对特定领域问题代码的调用,业务逻辑同特定领域问题的关系通过侧面来封装、维护.
这样原本分散在在整个应用程序中的变动就可以很好的管理起来。
tip
确实有点那么不太清晰,有点乱。不过在乱之前,我们可以选能理解的部分先看一下:
- 侧面(也就是切面) 用来描述分散在对象、类或函数中的横切关注点。
重点在这,分散在对象中的横切关注点,可以猜一下是什么,应该就是不同对象之间公用的部分 - 侧面的概念源于对面向对象的程序设计的改进,它还可以用来改进传统的函数.
AOP 显然不是OOP的替代品,是OOP的一种补充。 - 从主关注点中分离出横切关注点是面向侧面的程序设计的核心概念。
具体到业务项目中来说,主关注点就是业务逻辑了。针对特定领域问题代码的调用,就是AOP要关注的部分
简而言之,AOP是针对业务处理过程中的切面(即非业务逻辑部分,例如错误处理,埋点,日志等)进行提取.
它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果(目的是降低耦合)。
具体到实现来说就是通过动态的方式将非主关注点部分插入到主关注点(一般是业务逻辑中)
说了这么多,可能不太明白,还是一起看代码吧。
埋点场景
很普遍的这么个场景,需要点击按钮之后进行信息上报。
假设我们有这么个logger的工具,可以进行上报:
const logger = console.log
//引入即可使用
logger('按钮被点击了')
那么,我们直接撸起来吧:
const doSomething = ()=>{
console.log('doSomething')
}
let clickHandler = ()=>{
logger('doSomething之前')
// n行代码
doSomething()
logger('doSomething之后')
//n 行代码
}
看起来也没什么的,简单粗暴。
如果有30个按钮,每个业务逻辑不同,都需要埋这个点(假设打点信息一致)。
我们30个函数里面,都要手动写这个方法的话,这也太坑爹了吧。
主要是与业务代码严重耦合,哪天不小心动了点其他内容,手抖误删了,就gg了。
后续维护的时候,简直噩梦。
仔细看一下,这不就是符合AOP的使用前提吗,那么试试AOP吧。
关注点划分
根据前面提的,可以划分下关注点。
| 主关注点 | 侧关注点 |
|---|---|
| 业务逻辑(doSomething) | 埋点信息 logger |
前面提到AOP关注的是步骤具体到例子来说其实就是插入logger的步骤。
插入时机无非时业务逻辑执行之前或者之后的阶段。
具体实现起来也不那么困难
实现思路
具体到js来说,由于语言本身的特性,天生就具有运行时动态插入逻辑的能力。
重点在于在原函数上增加其他功能并不改变函数本身。
毕竟函数可以接受一切形式的参数,当然函数也不例外了。
当传入一个函数的时候,我们要对其操作的余地就很大了,
保存原函数,然后利用后续参数加上call或apply,就可以达到我们的目的。
此外为了给函数都增加一个属性,我们在原型上操作就行了。
经典before或者after的实现
网上太多类似实现了,直接看代码好了:
// action 即为我们的侧关注点,即logger
Function.prototype.after = function (action) {
//保留当前函数,这里this指向运行函数即clickHandler
var func = this;
// return 被包装过的函数,这里就可以执行其他功能了。
// 并且该方法挂在Function.prototype上,
// 被返回的函数依然具有after属性,可以链式调用
return function () {
// 原函数执行,这里不考虑异步
var result = func.apply(this, arguments);
// 执行之后的操作
action.apply(this,arguments);
// 将执行结果返回
return result;
};
};
// before 实现类似,只不过执行顺序差别而已
Function.prototype.before = function (action) {
var func = this;
return function () {
action.apply(this,arguments);
return func.apply(this, arguments);
};
};
那么我们使用AOP改造之后的代码就如下了:
const doSomething = ()=>{
console.log('doSomething')
}
let clickHandler = ()=>{
// n行代码
doSomething()
//n 行代码
}
clickHandler = clickHandler.before(()=>{
logger('doSomething之前')
}).after(()=>{
logger('doSomething之后')
})
clickHandler() // 执行结果和预期一致
到这里就实现了面向切面编程,我们的业务逻辑里面只管业务本身,侧关注点通过这种方式来动态引入,与主逻辑解耦,更加纯净、易于维护。
结束语
到这里,简单的AOP就介绍完成了。利用这种模式结合我们js本身的特性,可以尝试更多的可能。
例如我们react中常见的HOC、es7的装饰者模式、HOF等,很多时候不得不感叹大牛们思想的精髓,会让我们有种顿悟的感觉。本文抛砖引玉,共同学习啦,对自己是总结和提高,更希望能帮助到需要的小伙伴。更多文章请移步我的博客
参考文章
AllyTeam - 用AOP改善javascript代码
深入浅出 Javascript Decorators 和 AOP 编程
前端解读面向切面编程(AOP)的更多相关文章
- Spring框架系列(4) - 深入浅出Spring核心之面向切面编程(AOP)
在Spring基础 - Spring简单例子引入Spring的核心中向你展示了AOP的基础含义,同时以此发散了一些AOP相关知识点; 本节将在此基础上进一步解读AOP的含义以及AOP的使用方式.@pd ...
- 设计模式之面向切面编程AOP
动态的将代码切入到指定的方法.指定位置上的编程思想就是面向切面的编程. 代码只有两种,一种是逻辑代码.另一种是非逻辑代码.逻辑代码就是实现功能的核心代码,非逻辑代码就是处理琐碎事务的代码,比如说获取连 ...
- Spring学习手札(二)面向切面编程AOP
AOP理解 Aspect Oriented Program面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. 但是,这种说法有些片面,因为在软件工程中,AOP的价值体现的并 ...
- Spring学习笔记:面向切面编程AOP(Aspect Oriented Programming)
一.面向切面编程AOP 目标:让我们可以“专心做事”,避免繁杂重复的功能编码 原理:将复杂的需求分解出不同方面,将公共功能集中解决 *****所谓面向切面编程,是一种通过预编译方式和运行期动态代理实现 ...
- Spring框架学习笔记(2)——面向切面编程AOP
介绍 概念 面向切面编程AOP与面向对象编程OOP有所不同,AOP不是对OOP的替换,而是对OOP的一种补充,AOP增强了OOP. 假设我们有几个业务代码,都调用了某个方法,按照OOP的思想,我们就会 ...
- Spring之控制反转——IoC、面向切面编程——AOP
控制反转——IoC 提出IoC的目的 为了解决对象之间的耦合度过高的问题,提出了IoC理论,用来实现对象之间的解耦. 什么是IoC IoC是Inversion of Control的缩写,译为控制 ...
- 【串线篇】面向切面编程AOP
面向切面编程AOP 描述:将某段代码“动态”的切入到“指定方法”的“指定位置”进行运行的一种编程方式 (其底层就是Java的动态代理)spring对其做了简化书写 场景: 1).AOP加日志保存到数据 ...
- 04 Spring:01.Spring框架简介&&02.程序间耦合&&03.Spring的 IOC 和 DI&&08.面向切面编程 AOP&&10.Spring中事务控制
spring共四天 第一天:spring框架的概述以及spring中基于XML的IOC配置 第二天:spring中基于注解的IOC和ioc的案例 第三天:spring中的aop和基于XML以及注解的A ...
- [译]如何在ASP.NET Core中实现面向切面编程(AOP)
原文地址:ASPECT ORIENTED PROGRAMMING USING PROXIES IN ASP.NET CORE 原文作者:ZANID HAYTAM 译文地址:如何在ASP.NET Cor ...
随机推荐
- ActiveMQ安装与入门程序 & JMS的消息结构
1.Activemq安装 直接到官网下载:记住apache的官网是域名反过来,比如我们找activemq就是activemq.apache.org. 最新版本要求最低的JDK是8,所以最好在电脑装多个 ...
- ubuntu14.04 安装 openssh-server
ubuntu自带的有openssh-client,所以可以通过 ssh username@host 来远程连接linux 可是要想通过ssh被连接,ubuntu系统需要有openssh-server, ...
- Python中的元类
从前面"Python对象"文章中了解到,在Python中一切都是对象,类可以创建实例对象,但是类本身也是对象. class C(object): pass c = C() prin ...
- php 日期格式转换万能公式
思路用strtotime转换时间的字符串 $t='2017-03-09 02:30'; echo(date('Y-m-d H-i', strtotime($t)));
- vss 日文文件路径的名字在中文系统下乱码
解决方式:tools-font 文字设置 日本語
- 连接Linux服务器操作Oracle数据库
连接Linux服务器操作Oracle数据库 由于项目已经上线,现场的数据库服务器不允许直接用Oracle的客户端plsqldev.exe来连接,只能通过Linux服务器的命令来操作. 以下是用Se ...
- centos环境自动化批量安装jdk软件脚本
自动化安装jdk软件部署脚本 准备工作: 1.在执行脚本的服务器上生成免密码公钥: 安装expect命令 yum install -y expect ssh-keygen 三次回车 2.将jdk-7u ...
- js学习、备忘
字符串使用单引号’abc’.(双引号也行.推荐:html→双引号,js→单引号)===严格等于.!==严格不等于if(x) 当x为undefined.null和0的时候都为false:需注意当x为0 ...
- STM32F412应用开发笔记之十:多组分气体分析仪设计验证
本次将NUCLEO-F412ZG应用于我们的多组分气体分析仪的实现试验,从整体上测试实际项目的应用情况. 一.项目概述 多组分气体分析仪是我公司近期研发的三个主要产品之一.采用模块化设计,可增减配置, ...
- visual studio 2017 installer 安装包制作过程出现的问题---此安装程序需要.NET Framework 版本 3.5,请安装该版本,然后重新运行此安装程序,可以从Web获得.NET Framework 。要立即做此事吗?
图一 visual studio 2017 installer 打包完成以后进行安装时,提示信息 “安装此安装程序需要.NET Framework 版本 3.5,请安装该版本,然后重新运行此安装程序, ...