uaop
v0.0.1-alpha.2
Published
unknown aop
Downloads
4
Readme
Unnamed AOP
一个 js 版的 aop 库, 能够无入侵的增加和改变函数或方法的行为.
基本概念
面向切面编程
通知(Advice)
在函数/方法执行的特定时机执行指定的逻辑. 主要有以下几个类型的通知:
- before: 在函数/方法执行前调用指定逻辑
- after: 在函数/方法执行后调用指定逻辑, 无论函数/方法是否执行成功
- afterReturning: 在函数/方法执行成功后调用指定逻辑
- afterThrowing: 在方法抛出异常后调用指定逻辑
- around: 在函数/方法调用之前和调用之后执行自定义的指定逻辑
切点(PointCut/Matcher)
切点(连接点筛选)功能, 为 string, RegExp, Function 三个类型之一, 指定符合匹配条件的方法才应用特定的通知逻辑
切面(Aspect/Advisor)
切面是通知和切点的结合, 通知和切点共同定义了切面的全部内容 - 是什么, 在何时和何处完成功能.
Advisor = {
// 切点/匹配器, 为字符串,正则,函数三种, 见 PointCut/Matcher
matcher: Matcher,
// 通知对象, 拥有 before, afterReturning, afterThrowing, after, around 中一个或多个方法
advices: {
before(...args) { //... },
after() { // ... },
afterReturning(returnValue) { // ... },
afterThrowing(exception) { // ... },
around(joinPoint) { // ... }
}
}
安装
node
npm install uaop
Browser global
<script src="path/uaop/dist/bundle.js"></script>
模块环境
import * as aop from 'uaop'; // es6
// var aop = require('uaop'); // AMD/CMD
// window.uaop // global
快速使用
import * as aop from 'uaop'; // es6
function doSomething() {
console.log('doSomething');
}
function beforeAdvice {
console.log('before doSomething');
}
// 函数拦截
let proxyFunc = aop.before(doSomething, beforeAdvice);
proxyFunc();
// 对象拦截
let obj = {doSomething};
let proxyObj = aop.before(obj, 'doSomething', beforeAdvice);
proxyObj.doSomething();
// 类拦截
class Do {
doSomething() {
console.log('doSomething');
}
}
let ProxyClass = aop.before(Do, 'doSomething', beforeAdvice);
let instance = new ProxyClass();
instance.doSomething();
API
Function API
提供针对函数执行拦截的API
before(functionToAdvise, beforeFunction)
返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数执行前, 执行 beforeFunction, beforeFunction 接收与 functionToAdvise 一致的参数
除非抛异常, 否则不会中断函数的执行
var functionToAdvise = function () {
console.log('functionToAdvise exec');
};
var advisedFunction = aop.before(functionToAdvise, function () {
console.log('arguments length:', argument.length);
});
// log:
// arguments length: 3
// functionToAdvise exec
advisedFunction(1, 2, 3);
afterReturning(functionToAdvise, afterReturningFunction)
返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数正常返回后, 执行 afterReturningFunction, afterReturningFunction 接收 functionToAdvise 执行后的返回结果作为唯一参数, 不影响返回结果.
var functionToAdvise = function () {
console.log('functionToAdvise exec');
return 'functionToAdvise';
};
var advisedFunction = aop.afterReturning(functionToAdvise, function (returnValue) {
console.log('return value: ', returnValue);
});
// log:
// functionToAdvise exec
// return value: functionToAdvise
advisedFunction();
afterThrowing(functionToAdvise, afterThrowingFunction)
返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数抛出异常时, 执行 afterThrowingFunction, afterThrowingFunction 接收 functionToAdvise 抛出的异常对象作为唯一参数.
通知不会吞噬原有异常, 会在 afterThrowingFunction 执行完毕后, 抛出原有异常
var functionToAdvise = function (throwError) {
console.log('functionToAdvise exec');
if(throwError) {
throw new Error('functionToAdvise error');
}
};
var advisedFunction = aop.afterThrowing(functionToAdvise, function (e) {
console.log('execption: ', e.message);
});
// log:
// functionToAdvise exec
advisedFunction();
// log:
// functionToAdvise exec
// execption: functionToAdvise error
advisedFunction(true);
after(functionToAdvise, afterFunction)
返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数正常返回或抛出异常时, 执行 afterFunction
通知不会吞噬原有异常, 会在 afterFunction 执行完毕后, 抛出原有异常
var functionToAdvise = function (throwError) {
if(throwError) {
console.log('functionToAdvise exception');
throw new Error('error');
}
console.log('functionToAdvise normal exec');
};
var advisedFunction = aop.after(functionToAdvise, function () {
console.log('after functionToAdvise');
});
// log:
// functionToAdvise normal exec
// after functionToAdvise
advisedFunction();
// log:
// functionToAdvise exception
// after functionToAdvise
advisedFunction(true);
around(functionToAdvise, aroundFunction)
返回一个新的函数, 执行逻辑为, 执行 aroundFunction, aroundFunction 接收一个 ProceedingJoinPoint 对象作为参数, 调用其 proceed/proceedApply 方法将执行 functionToAdvise.
var functionToAdvise = function () {
console.log('functionToAdvise exec arguments: ', [].slice.call(arguments, 0));
return 'functionToAdvise return value';
};
var advisedFunction = aop.around(functionToAdvise, function (joinPoint) {
console.log('before functionToAdvise exec');
// proceed/proceddApply 可以多次调用, 会多次执行原函数, proceedApply 可以改变 this 和参数信息
var result = joinPoint.proceed();
result = joinPoint.proceedApply(null, [1, 2]);
console.log('functionToAdvise exec result: ', result);
console.log('after functionToAdvise exec');
});
// log:
// before functionToAdvise exec
// functionToAdvise exec arguments: 1,2,3
// functionToAdvise exec arguments: 1,2
// functionToAdvise exec result: functionToAdvise return value
// after functionToAdvise exec
advisedFunction(1, 2, 3);
ProceedingJoinPoint
joinPoint = {
// 函数被调用时的上下文
target: Object,
// 传给外层函数的参数
args: Array,
// 原方法名或函数名
method: string,
// 被调用时, 会调用被拦截的原函数, 并传入原始参数
proceed: Function,
// 被调用时, 会调用被拦截的原函数, 首个参数为被拦截函数要执行时的上下文, 第二个参数为要传递给被拦截函数的参数数组
proceedApply: Function
}
createFunctionProxy(functionToAdvise, advices)
创建一个组装了多个通知行为的函数代理, advices 为拥有 before, afterReturning, afterThrowing, after, around 中一个或多个方法的对象.
Object Method API
提供针对对象方法的拦截。
每个拦截接口都接收三个参数:被拦截对象,方法匹配规则 matcher,通知执行函数。
matcher 可为 string, RegExp, Function 的任意一种,为 Function 时,接收被拦截对象和当前方法名作为参数,执行结果返回 true 时,匹配成功,会对该方法执行拦截。
每个拦截接口都会返回一个原对象的代理对象,代理对象会针对符合匹配规则的方法封装,根据通知类型,在方法执行的不同阶段,执行相关的通知逻辑。
注:原对象不受任何影响
before(objectToAdvise, matcher, beforeFunction)
返回一个新的代理对象, 在 matcher 匹配的方法执行前,会执行 beforeFunction,beforeFunction 接收匹配方法执行时的参数
除非抛异常, 否则不会中断匹配方法的执行
var toAdvise = {
method: function () {
console.log('method exec');
}
};
var advisedObject = aop.before(toAdvise, 'method', function (arg) {
console.log('before method exec');
console.log(arg);
});
// log:
// before method exec
// a
// method exec
advisedObject.method('a');
// log:
// method exec
toAdvise.method('a');
afterReturning(objectToAdvise, matcher, afterReturningFunction)
返回一个新的代理对象, 在 matcher 匹配的方法正常执行后, 执行 afterReturningFunction, afterReturningFunction 接收匹配方法执行后的返回结果作为唯一参数, 不影响返回结果.
var toAdvise = {
method: function () {
console.log('method exec');
return 'toAdivse method result';
}
};
var advisedObject = aop.afterReturning(toAdvise, 'method', function (returnValue) {
console.log('return value: ', returnValue);
});
// log:
// method exec
// return value: toAdivse method result
advisedObject.method();
afterThrowing(objectToAdvise, matcher, afterThrowingFunction)
返回一个新的代理对象, 在 matcher 匹配的方法抛出异常后, 执行 afterThrowingFunction, afterThrowingFunction 接收匹配方法抛出的异常对象作为唯一参数.
通知不会吞噬原有异常, 会在 afterThrowingFunction 执行完毕后, 抛出原有异常
var toAdvise = {
method: function (throwError) {
console.log('method exec');
if(throwError) {
throw new Error('method error');
}
}
};
var advisedObject = aop.afterThrowing(toAdvise, 'method', function (e) {
console.log('execption: ', e.message);
});
// log:
// method exec
advisedObject.method();
// log:
// method exec
// execption: method error
advisedObject.method(true);
after(objectToAdvise, matcher, afterFunction)
返回一个新的代理对象, 在 matcher 匹配的方法正常返回或抛出异常后, 执行 afterFunction。
通知不会吞噬原有异常, 会在 afterFunction 执行完毕后, 抛出原有异常
var toAdvise = {
method: function (throwError) {
if(throwError) {
console.log('method exception');
throw new Error('error');
}
console.log('method exec');
}
};
var advisedObject = aop.after(toAdvise, 'method', function () {
console.log('after method exec');
});
// log:
// method exec
// after method exec
advisedObject.method();
// log:
// method exception
// after method exec
advisedObject.method(true);
around(objectToAdvise, matcher, aroundFunction)
返回一个新的代理对象, 在 matcher 匹配的方法执行时, 执行 aroundFunction, aroundFunction 接收一个 ProceedingJoinPoint 对象作为参数, 调用其 proceed/proceedApply 方法将执行原方法.
var toAdvise = {
method: function () {
console.log('method exec arguments: ', [].slice.call(arguments, 0));
return 'method return value';
}
};
var advisedObject = aop.around(toAdvise, 'method', function (joinPoint) {
console.log('before method exec');
// proceed/proceedApply 可以多次调用, 会多次执行原方法, proceedApply 可以改变 this 和参数信息
var result = joinPoint.proceed();
result = joinPoint.proceedApply(null, [1, 2]);
console.log('method exec result: ', result);
console.log('after method exec');
});
// log:
// before method exec
// method exec arguments: 1,2,3
// method exec arguments: 1,2
// method exec result: method return value
// after method exec
advisedObject.method(1, 2, 3);
createObjectProxy(objectToAdvise, matcher, advices)
创建一个组装了通知行为的对象代理, 会重写符合匹配规则的方法, 织入通知逻辑.
advice 拥有 before, afterReturning, afterThrowing, after, around 中一个或多个方法的对象.
ProceedingJoinPoint
同Function API 下的 ProceedingJoinPoint
Matcher
matcher 可以为以下三种类型:
- string 匹配拦截对象中属性名与 matcher 相等的方法。
- RegExp 匹配拦截对象中属性名符合 matcher 规则的方法。
- Function 匹配拦截对象中属性名符合 matcher 执行结果的方法, matcher 接收拦截对象和当前属性名称作为参数,返回 true 则表示匹配成功。
var toAdvise = {
method: function () {},
foo: function () {},
foo1: function () {},
foo2: function () {},
init: function () {}
};
// 将拦截 toAdvise.method
var advisedObject = aop.before(toAdvise, 'method', function () {});
// 将拦截 toAdvise.foo, toAdvise.foo1, toAdvise.foo2
var advisedObject = aop.before(toAdvise, /^foo/, function () {});
var fnMatcher = function (obj, name) {
return name !== 'init';
};
// 将拦截 toAdvise.foo, toAdvise.foo1, toAdvise.foo2, toAdvise.method
var advisedObject = aop.before(toAdvise, fnMatcher, function () {});
Class Method API
提供针对Class方法拦截的 API
createClassProxy(Class, matcher, advices)
创建一个组装了通知行为的类代理, 会重写符合匹配规则的方法, 织入通知逻辑.
advice 拥有 before, afterReturning, afterThrowing, after, around 中一个或多个方法的对象.