Skip to content

Repository files navigation

Unnamed AOP

一个 js 版的 aop 库, 能够无入侵的增加和改变函数或方法的行为.

基本概念

通知(Advice)

在函数/方法执行的特定时机执行指定的逻辑. 主要有以下几个类型的通知:

  1. before: 在函数/方法执行前调用指定逻辑
  2. after: 在函数/方法执行后调用指定逻辑, 无论函数/方法是否执行成功
  3. afterReturning: 在函数/方法执行成功后调用指定逻辑
  4. afterThrowing: 在方法抛出异常后调用指定逻辑
  5. around: 在函数/方法调用之前和调用之后执行自定义的指定逻辑

切点(PointCut/Matcher)

切点(连接点筛选)功能, 为 string, RegExp, Function 三个类型之一, 指定符合匹配条件的方法才应用特定的通知逻辑

切面(Aspect/Advisor)

切面是通知和切点的结合, 通知和切点共同定义了切面的全部内容 - 是什么, 在何时和何处完成功能.

Advisor={// 切点/匹配器, 为字符串,正则,函数三种, 见 PointCut/Matchermatcher: Matcher,// 通知对象, 拥有 before, afterReturning, afterThrowing, after, around 中一个或多个方法advices: {before(...args){/* ... */},after(){/* ... */},afterReturning(returnValue){/* ... */},afterThrowing(){/* ... */},around(joinPoint){/* ... */}}}

安装

node

npm install uaop

Browser global

<scriptsrc="path/uaop/dist/bundle.js"></script>

模块环境

import*asaopfrom'uaop';// es6// var aop = require('uaop'); // AMD/CMD// window.uaop // global

快速使用

import*asaopfrom'uaop';// es6functiondoSomething(){console.log('doSomething');}functionbeforeAdvice{console.log('before doSomething');}// 函数拦截letproxyFunc=aop.before(doSomething,beforeAdvice);proxyFunc();// 对象拦截letobj={doSomething};letproxyObj=aop.before(obj,'doSomething',beforeAdvice);proxyObj.doSomething();// 类拦截classDo{doSomething(){console.log('doSomething');}}letProxyClass=aop.before(Do,'doSomething',beforeAdvice);letinstance=newProxyClass();instance.doSomething();

API

Function API

提供针对函数执行拦截的API

before(functionToAdvise, beforeFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数执行前, 执行 beforeFunction, beforeFunction 接收与 functionToAdvise 一致的参数

除非抛异常, 否则不会中断函数的执行

varfunctionToAdvise=function(){console.log('functionToAdvise exec');};varadvisedFunction=aop.before(functionToAdvise,function(){console.log('arguments length:',argument.length);});// log:// arguments length: 3// functionToAdvise execadvisedFunction(1,2,3);

afterReturning(functionToAdvise, afterReturningFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数正常返回后, 执行 afterReturningFunction, afterReturningFunction 接收 functionToAdvise 执行后的返回结果作为唯一参数, 不影响返回结果.

varfunctionToAdvise=function(){console.log('functionToAdvise exec');return'functionToAdvise';};varadvisedFunction=aop.afterReturning(functionToAdvise,function(returnValue){console.log('return value: ',returnValue);});// log:// functionToAdvise exec// return value: functionToAdviseadvisedFunction();

afterThrowing(functionToAdvise, afterThrowingFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数抛出异常时, 执行 afterThrowingFunction, afterThrowingFunction 接收 functionToAdvise 抛出的异常对象作为唯一参数.

通知不会吞噬原有异常, 会在 afterThrowingFunction 执行完毕后, 抛出原有异常

varfunctionToAdvise=function(throwError){console.log('functionToAdvise exec');if(throwError){thrownewError('functionToAdvise error');}};varadvisedFunction=aop.afterThrowing(functionToAdvise,function(e){console.log('execption: ',e.message);});// log:// functionToAdvise execadvisedFunction();// log:// functionToAdvise exec// execption: functionToAdvise erroradvisedFunction(true);

after(functionToAdvise, afterFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数正常返回或抛出异常时, 执行 afterFunction

通知不会吞噬原有异常, 会在 afterFunction 执行完毕后, 抛出原有异常

varfunctionToAdvise=function(throwError){if(throwError){console.log('functionToAdvise exception');thrownewError('error');}console.log('functionToAdvise normal exec');};varadvisedFunction=aop.after(functionToAdvise,function(){console.log('after functionToAdvise');});// log:// functionToAdvise normal exec// after functionToAdviseadvisedFunction();// log:// functionToAdvise exception// after functionToAdviseadvisedFunction(true);

around(functionToAdvise, aroundFunction)

返回一个新的函数, 执行逻辑为, 执行 aroundFunction, aroundFunction 接收一个 ProceedingJoinPoint 对象作为参数, 调用其 proceed/proceedApply 方法将执行 functionToAdvise.

varfunctionToAdvise=function(){console.log('functionToAdvise exec arguments: ',[].slice.call(arguments,0));return'functionToAdvise return value';};varadvisedFunction=aop.around(functionToAdvise,function(joinPoint){console.log('before functionToAdvise exec');// proceed/proceddApply 可以多次调用, 会多次执行原函数, proceedApply 可以改变 this 和参数信息varresult=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 execadvisedFunction(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 接收匹配方法执行时的参数

除非抛异常, 否则不会中断匹配方法的执行

vartoAdvise={method: function(){console.log('method exec');}};varadvisedObject=aop.before(toAdvise,'method',function(arg){console.log('before method exec');console.log(arg);});// log:// before method exec// a// method execadvisedObject.method('a');// log:// method exectoAdvise.method('a');

afterReturning(objectToAdvise, matcher, afterReturningFunction)

返回一个新的代理对象, 在 matcher 匹配的方法正常执行后, 执行 afterReturningFunction, afterReturningFunction 接收匹配方法执行后的返回结果作为唯一参数, 不影响返回结果.

vartoAdvise={method: function(){console.log('method exec');return'toAdivse method result';}};varadvisedObject=aop.afterReturning(toAdvise,'method',function(returnValue){console.log('return value: ',returnValue);});// log:// method exec// return value: toAdivse method resultadvisedObject.method();

afterThrowing(objectToAdvise, matcher, afterThrowingFunction)

返回一个新的代理对象, 在 matcher 匹配的方法抛出异常后, 执行 afterThrowingFunction, afterThrowingFunction 接收匹配方法抛出的异常对象作为唯一参数.

通知不会吞噬原有异常, 会在 afterThrowingFunction 执行完毕后, 抛出原有异常

vartoAdvise={method: function(throwError){console.log('method exec');if(throwError){thrownewError('method error');}}};varadvisedObject=aop.afterThrowing(toAdvise,'method',function(e){console.log('execption: ',e.message);});// log:// method execadvisedObject.method();// log:// method exec// execption: method erroradvisedObject.method(true);

after(objectToAdvise, matcher, afterFunction)

返回一个新的代理对象, 在 matcher 匹配的方法正常返回或抛出异常后, 执行 afterFunction。

通知不会吞噬原有异常, 会在 afterFunction 执行完毕后, 抛出原有异常

vartoAdvise={method: function(throwError){if(throwError){console.log('method exception');thrownewError('error');}console.log('method exec');}};varadvisedObject=aop.after(toAdvise,'method',function(){console.log('after method exec');});// log:// method exec// after method execadvisedObject.method();// log:// method exception// after method execadvisedObject.method(true);

around(objectToAdvise, matcher, aroundFunction)

返回一个新的代理对象, 在 matcher 匹配的方法执行时, 执行 aroundFunction, aroundFunction 接收一个 ProceedingJoinPoint 对象作为参数, 调用其 proceed/proceedApply 方法将执行原方法.

vartoAdvise={method: function(){console.log('method exec arguments: ',[].slice.call(arguments,0));return'method return value';}};varadvisedObject=aop.around(toAdvise,'method',function(joinPoint){console.log('before method exec');// proceed/proceedApply 可以多次调用, 会多次执行原方法, proceedApply 可以改变 this 和参数信息varresult=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 execadvisedObject.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 则表示匹配成功。
vartoAdvise={method: function(){},foo: function(){},foo1: function(){},foo2: function(){},init: function(){}};// 将拦截 toAdvise.methodvaradvisedObject=aop.before(toAdvise,'method',function(){});// 将拦截 toAdvise.foo, toAdvise.foo1, toAdvise.foo2varadvisedObject=aop.before(toAdvise,/^foo/,function(){});varfnMatcher=function(obj,name){returnname!=='init';};// 将拦截 toAdvise.foo, toAdvise.foo1, toAdvise.foo2, toAdvise.methodvaradvisedObject=aop.before(toAdvise,fnMatcher,function(){});

Class Method API

提供针对Class方法拦截的 API

createClassProxy(Class, matcher, advices)

创建一个组装了通知行为的类代理, 会重写符合匹配规则的方法, 织入通知逻辑.

advice 拥有 before, afterReturning, afterThrowing, after, around 中一个或多个方法的对象.

About

Aspect oriented programming utilities

Resources

Stars

12 stars

Watchers

10 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - ecomfe/aop: Aspect oriented programming utilities · GitHub
Skip to content

Repository files navigation

Unnamed AOP

一个 js 版的 aop 库, 能够无入侵的增加和改变函数或方法的行为.

基本概念

通知(Advice)

在函数/方法执行的特定时机执行指定的逻辑. 主要有以下几个类型的通知:

  1. before: 在函数/方法执行前调用指定逻辑
  2. after: 在函数/方法执行后调用指定逻辑, 无论函数/方法是否执行成功
  3. afterReturning: 在函数/方法执行成功后调用指定逻辑
  4. afterThrowing: 在方法抛出异常后调用指定逻辑
  5. around: 在函数/方法调用之前和调用之后执行自定义的指定逻辑

切点(PointCut/Matcher)

切点(连接点筛选)功能, 为 string, RegExp, Function 三个类型之一, 指定符合匹配条件的方法才应用特定的通知逻辑

切面(Aspect/Advisor)

切面是通知和切点的结合, 通知和切点共同定义了切面的全部内容 - 是什么, 在何时和何处完成功能.

Advisor={// 切点/匹配器, 为字符串,正则,函数三种, 见 PointCut/Matchermatcher: Matcher,// 通知对象, 拥有 before, afterReturning, afterThrowing, after, around 中一个或多个方法advices: {before(...args){/* ... */},after(){/* ... */},afterReturning(returnValue){/* ... */},afterThrowing(){/* ... */},around(joinPoint){/* ... */}}}

安装

node

npm install uaop

Browser global

<scriptsrc="path/uaop/dist/bundle.js"></script>

模块环境

import*asaopfrom'uaop';// es6// var aop = require('uaop'); // AMD/CMD// window.uaop // global

快速使用

import*asaopfrom'uaop';// es6functiondoSomething(){console.log('doSomething');}functionbeforeAdvice{console.log('before doSomething');}// 函数拦截letproxyFunc=aop.before(doSomething,beforeAdvice);proxyFunc();// 对象拦截letobj={doSomething};letproxyObj=aop.before(obj,'doSomething',beforeAdvice);proxyObj.doSomething();// 类拦截classDo{doSomething(){console.log('doSomething');}}letProxyClass=aop.before(Do,'doSomething',beforeAdvice);letinstance=newProxyClass();instance.doSomething();

API

Function API

提供针对函数执行拦截的API

before(functionToAdvise, beforeFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数执行前, 执行 beforeFunction, beforeFunction 接收与 functionToAdvise 一致的参数

除非抛异常, 否则不会中断函数的执行

varfunctionToAdvise=function(){console.log('functionToAdvise exec');};varadvisedFunction=aop.before(functionToAdvise,function(){console.log('arguments length:',argument.length);});// log:// arguments length: 3// functionToAdvise execadvisedFunction(1,2,3);

afterReturning(functionToAdvise, afterReturningFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数正常返回后, 执行 afterReturningFunction, afterReturningFunction 接收 functionToAdvise 执行后的返回结果作为唯一参数, 不影响返回结果.

varfunctionToAdvise=function(){console.log('functionToAdvise exec');return'functionToAdvise';};varadvisedFunction=aop.afterReturning(functionToAdvise,function(returnValue){console.log('return value: ',returnValue);});// log:// functionToAdvise exec// return value: functionToAdviseadvisedFunction();

afterThrowing(functionToAdvise, afterThrowingFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数抛出异常时, 执行 afterThrowingFunction, afterThrowingFunction 接收 functionToAdvise 抛出的异常对象作为唯一参数.

通知不会吞噬原有异常, 会在 afterThrowingFunction 执行完毕后, 抛出原有异常

varfunctionToAdvise=function(throwError){console.log('functionToAdvise exec');if(throwError){thrownewError('functionToAdvise error');}};varadvisedFunction=aop.afterThrowing(functionToAdvise,function(e){console.log('execption: ',e.message);});// log:// functionToAdvise execadvisedFunction();// log:// functionToAdvise exec// execption: functionToAdvise erroradvisedFunction(true);

after(functionToAdvise, afterFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数正常返回或抛出异常时, 执行 afterFunction

通知不会吞噬原有异常, 会在 afterFunction 执行完毕后, 抛出原有异常

varfunctionToAdvise=function(throwError){if(throwError){console.log('functionToAdvise exception');thrownewError('error');}console.log('functionToAdvise normal exec');};varadvisedFunction=aop.after(functionToAdvise,function(){console.log('after functionToAdvise');});// log:// functionToAdvise normal exec// after functionToAdviseadvisedFunction();// log:// functionToAdvise exception// after functionToAdviseadvisedFunction(true);

around(functionToAdvise, aroundFunction)

返回一个新的函数, 执行逻辑为, 执行 aroundFunction, aroundFunction 接收一个 ProceedingJoinPoint 对象作为参数, 调用其 proceed/proceedApply 方法将执行 functionToAdvise.

varfunctionToAdvise=function(){console.log('functionToAdvise exec arguments: ',[].slice.call(arguments,0));return'functionToAdvise return value';};varadvisedFunction=aop.around(functionToAdvise,function(joinPoint){console.log('before functionToAdvise exec');// proceed/proceddApply 可以多次调用, 会多次执行原函数, proceedApply 可以改变 this 和参数信息varresult=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 execadvisedFunction(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 接收匹配方法执行时的参数

除非抛异常, 否则不会中断匹配方法的执行

vartoAdvise={method: function(){console.log('method exec');}};varadvisedObject=aop.before(toAdvise,'method',function(arg){console.log('before method exec');console.log(arg);});// log:// before method exec// a// method execadvisedObject.method('a');// log:// method exectoAdvise.method('a');

afterReturning(objectToAdvise, matcher, afterReturningFunction)

返回一个新的代理对象, 在 matcher 匹配的方法正常执行后, 执行 afterReturningFunction, afterReturningFunction 接收匹配方法执行后的返回结果作为唯一参数, 不影响返回结果.

vartoAdvise={method: function(){console.log('method exec');return'toAdivse method result';}};varadvisedObject=aop.afterReturning(toAdvise,'method',function(returnValue){console.log('return value: ',returnValue);});// log:// method exec// return value: toAdivse method resultadvisedObject.method();

afterThrowing(objectToAdvise, matcher, afterThrowingFunction)

返回一个新的代理对象, 在 matcher 匹配的方法抛出异常后, 执行 afterThrowingFunction, afterThrowingFunction 接收匹配方法抛出的异常对象作为唯一参数.

通知不会吞噬原有异常, 会在 afterThrowingFunction 执行完毕后, 抛出原有异常

vartoAdvise={method: function(throwError){console.log('method exec');if(throwError){thrownewError('method error');}}};varadvisedObject=aop.afterThrowing(toAdvise,'method',function(e){console.log('execption: ',e.message);});// log:// method execadvisedObject.method();// log:// method exec// execption: method erroradvisedObject.method(true);

after(objectToAdvise, matcher, afterFunction)

返回一个新的代理对象, 在 matcher 匹配的方法正常返回或抛出异常后, 执行 afterFunction。

通知不会吞噬原有异常, 会在 afterFunction 执行完毕后, 抛出原有异常

vartoAdvise={method: function(throwError){if(throwError){console.log('method exception');thrownewError('error');}console.log('method exec');}};varadvisedObject=aop.after(toAdvise,'method',function(){console.log('after method exec');});// log:// method exec// after method execadvisedObject.method();// log:// method exception// after method execadvisedObject.method(true);

around(objectToAdvise, matcher, aroundFunction)

返回一个新的代理对象, 在 matcher 匹配的方法执行时, 执行 aroundFunction, aroundFunction 接收一个 ProceedingJoinPoint 对象作为参数, 调用其 proceed/proceedApply 方法将执行原方法.

vartoAdvise={method: function(){console.log('method exec arguments: ',[].slice.call(arguments,0));return'method return value';}};varadvisedObject=aop.around(toAdvise,'method',function(joinPoint){console.log('before method exec');// proceed/proceedApply 可以多次调用, 会多次执行原方法, proceedApply 可以改变 this 和参数信息varresult=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 execadvisedObject.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 则表示匹配成功。
vartoAdvise={method: function(){},foo: function(){},foo1: function(){},foo2: function(){},init: function(){}};// 将拦截 toAdvise.methodvaradvisedObject=aop.before(toAdvise,'method',function(){});// 将拦截 toAdvise.foo, toAdvise.foo1, toAdvise.foo2varadvisedObject=aop.before(toAdvise,/^foo/,function(){});varfnMatcher=function(obj,name){returnname!=='init';};// 将拦截 toAdvise.foo, toAdvise.foo1, toAdvise.foo2, toAdvise.methodvaradvisedObject=aop.before(toAdvise,fnMatcher,function(){});

Class Method API

提供针对Class方法拦截的 API

createClassProxy(Class, matcher, advices)

创建一个组装了通知行为的类代理, 会重写符合匹配规则的方法, 织入通知逻辑.

advice 拥有 before, afterReturning, afterThrowing, after, around 中一个或多个方法的对象.

About

Aspect oriented programming utilities

Resources

Stars

12 stars

Watchers

10 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - ecomfe/aop: Aspect oriented programming utilities · GitHub
Skip to content

Repository files navigation

Unnamed AOP

一个 js 版的 aop 库, 能够无入侵的增加和改变函数或方法的行为.

基本概念

通知(Advice)

在函数/方法执行的特定时机执行指定的逻辑. 主要有以下几个类型的通知:

  1. before: 在函数/方法执行前调用指定逻辑
  2. after: 在函数/方法执行后调用指定逻辑, 无论函数/方法是否执行成功
  3. afterReturning: 在函数/方法执行成功后调用指定逻辑
  4. afterThrowing: 在方法抛出异常后调用指定逻辑
  5. around: 在函数/方法调用之前和调用之后执行自定义的指定逻辑

切点(PointCut/Matcher)

切点(连接点筛选)功能, 为 string, RegExp, Function 三个类型之一, 指定符合匹配条件的方法才应用特定的通知逻辑

切面(Aspect/Advisor)

切面是通知和切点的结合, 通知和切点共同定义了切面的全部内容 - 是什么, 在何时和何处完成功能.

Advisor={// 切点/匹配器, 为字符串,正则,函数三种, 见 PointCut/Matchermatcher: Matcher,// 通知对象, 拥有 before, afterReturning, afterThrowing, after, around 中一个或多个方法advices: {before(...args){/* ... */},after(){/* ... */},afterReturning(returnValue){/* ... */},afterThrowing(){/* ... */},around(joinPoint){/* ... */}}}

安装

node

npm install uaop

Browser global

<scriptsrc="path/uaop/dist/bundle.js"></script>

模块环境

import*asaopfrom'uaop';// es6// var aop = require('uaop'); // AMD/CMD// window.uaop // global

快速使用

import*asaopfrom'uaop';// es6functiondoSomething(){console.log('doSomething');}functionbeforeAdvice{console.log('before doSomething');}// 函数拦截letproxyFunc=aop.before(doSomething,beforeAdvice);proxyFunc();// 对象拦截letobj={doSomething};letproxyObj=aop.before(obj,'doSomething',beforeAdvice);proxyObj.doSomething();// 类拦截classDo{doSomething(){console.log('doSomething');}}letProxyClass=aop.before(Do,'doSomething',beforeAdvice);letinstance=newProxyClass();instance.doSomething();

API

Function API

提供针对函数执行拦截的API

before(functionToAdvise, beforeFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数执行前, 执行 beforeFunction, beforeFunction 接收与 functionToAdvise 一致的参数

除非抛异常, 否则不会中断函数的执行

varfunctionToAdvise=function(){console.log('functionToAdvise exec');};varadvisedFunction=aop.before(functionToAdvise,function(){console.log('arguments length:',argument.length);});// log:// arguments length: 3// functionToAdvise execadvisedFunction(1,2,3);

afterReturning(functionToAdvise, afterReturningFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数正常返回后, 执行 afterReturningFunction, afterReturningFunction 接收 functionToAdvise 执行后的返回结果作为唯一参数, 不影响返回结果.

varfunctionToAdvise=function(){console.log('functionToAdvise exec');return'functionToAdvise';};varadvisedFunction=aop.afterReturning(functionToAdvise,function(returnValue){console.log('return value: ',returnValue);});// log:// functionToAdvise exec// return value: functionToAdviseadvisedFunction();

afterThrowing(functionToAdvise, afterThrowingFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数抛出异常时, 执行 afterThrowingFunction, afterThrowingFunction 接收 functionToAdvise 抛出的异常对象作为唯一参数.

通知不会吞噬原有异常, 会在 afterThrowingFunction 执行完毕后, 抛出原有异常

varfunctionToAdvise=function(throwError){console.log('functionToAdvise exec');if(throwError){thrownewError('functionToAdvise error');}};varadvisedFunction=aop.afterThrowing(functionToAdvise,function(e){console.log('execption: ',e.message);});// log:// functionToAdvise execadvisedFunction();// log:// functionToAdvise exec// execption: functionToAdvise erroradvisedFunction(true);

after(functionToAdvise, afterFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数正常返回或抛出异常时, 执行 afterFunction

通知不会吞噬原有异常, 会在 afterFunction 执行完毕后, 抛出原有异常

varfunctionToAdvise=function(throwError){if(throwError){console.log('functionToAdvise exception');thrownewError('error');}console.log('functionToAdvise normal exec');};varadvisedFunction=aop.after(functionToAdvise,function(){console.log('after functionToAdvise');});// log:// functionToAdvise normal exec// after functionToAdviseadvisedFunction();// log:// functionToAdvise exception// after functionToAdviseadvisedFunction(true);

around(functionToAdvise, aroundFunction)

返回一个新的函数, 执行逻辑为, 执行 aroundFunction, aroundFunction 接收一个 ProceedingJoinPoint 对象作为参数, 调用其 proceed/proceedApply 方法将执行 functionToAdvise.

varfunctionToAdvise=function(){console.log('functionToAdvise exec arguments: ',[].slice.call(arguments,0));return'functionToAdvise return value';};varadvisedFunction=aop.around(functionToAdvise,function(joinPoint){console.log('before functionToAdvise exec');// proceed/proceddApply 可以多次调用, 会多次执行原函数, proceedApply 可以改变 this 和参数信息varresult=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 execadvisedFunction(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 接收匹配方法执行时的参数

除非抛异常, 否则不会中断匹配方法的执行

vartoAdvise={method: function(){console.log('method exec');}};varadvisedObject=aop.before(toAdvise,'method',function(arg){console.log('before method exec');console.log(arg);});// log:// before method exec// a// method execadvisedObject.method('a');// log:// method exectoAdvise.method('a');

afterReturning(objectToAdvise, matcher, afterReturningFunction)

返回一个新的代理对象, 在 matcher 匹配的方法正常执行后, 执行 afterReturningFunction, afterReturningFunction 接收匹配方法执行后的返回结果作为唯一参数, 不影响返回结果.

vartoAdvise={method: function(){console.log('method exec');return'toAdivse method result';}};varadvisedObject=aop.afterReturning(toAdvise,'method',function(returnValue){console.log('return value: ',returnValue);});// log:// method exec// return value: toAdivse method resultadvisedObject.method();

afterThrowing(objectToAdvise, matcher, afterThrowingFunction)

返回一个新的代理对象, 在 matcher 匹配的方法抛出异常后, 执行 afterThrowingFunction, afterThrowingFunction 接收匹配方法抛出的异常对象作为唯一参数.

通知不会吞噬原有异常, 会在 afterThrowingFunction 执行完毕后, 抛出原有异常

vartoAdvise={method: function(throwError){console.log('method exec');if(throwError){thrownewError('method error');}}};varadvisedObject=aop.afterThrowing(toAdvise,'method',function(e){console.log('execption: ',e.message);});// log:// method execadvisedObject.method();// log:// method exec// execption: method erroradvisedObject.method(true);

after(objectToAdvise, matcher, afterFunction)

返回一个新的代理对象, 在 matcher 匹配的方法正常返回或抛出异常后, 执行 afterFunction。

通知不会吞噬原有异常, 会在 afterFunction 执行完毕后, 抛出原有异常

vartoAdvise={method: function(throwError){if(throwError){console.log('method exception');thrownewError('error');}console.log('method exec');}};varadvisedObject=aop.after(toAdvise,'method',function(){console.log('after method exec');});// log:// method exec// after method execadvisedObject.method();// log:// method exception// after method execadvisedObject.method(true);

around(objectToAdvise, matcher, aroundFunction)

返回一个新的代理对象, 在 matcher 匹配的方法执行时, 执行 aroundFunction, aroundFunction 接收一个 ProceedingJoinPoint 对象作为参数, 调用其 proceed/proceedApply 方法将执行原方法.

vartoAdvise={method: function(){console.log('method exec arguments: ',[].slice.call(arguments,0));return'method return value';}};varadvisedObject=aop.around(toAdvise,'method',function(joinPoint){console.log('before method exec');// proceed/proceedApply 可以多次调用, 会多次执行原方法, proceedApply 可以改变 this 和参数信息varresult=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 execadvisedObject.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 则表示匹配成功。
vartoAdvise={method: function(){},foo: function(){},foo1: function(){},foo2: function(){},init: function(){}};// 将拦截 toAdvise.methodvaradvisedObject=aop.before(toAdvise,'method',function(){});// 将拦截 toAdvise.foo, toAdvise.foo1, toAdvise.foo2varadvisedObject=aop.before(toAdvise,/^foo/,function(){});varfnMatcher=function(obj,name){returnname!=='init';};// 将拦截 toAdvise.foo, toAdvise.foo1, toAdvise.foo2, toAdvise.methodvaradvisedObject=aop.before(toAdvise,fnMatcher,function(){});

Class Method API

提供针对Class方法拦截的 API

createClassProxy(Class, matcher, advices)

创建一个组装了通知行为的类代理, 会重写符合匹配规则的方法, 织入通知逻辑.

advice 拥有 before, afterReturning, afterThrowing, after, around 中一个或多个方法的对象.

About

Aspect oriented programming utilities

Resources

Stars

12 stars

Watchers

10 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - ecomfe/aop: Aspect oriented programming utilities · GitHub
Skip to content

Repository files navigation

Unnamed AOP

一个 js 版的 aop 库, 能够无入侵的增加和改变函数或方法的行为.

基本概念

通知(Advice)

在函数/方法执行的特定时机执行指定的逻辑. 主要有以下几个类型的通知:

  1. before: 在函数/方法执行前调用指定逻辑
  2. after: 在函数/方法执行后调用指定逻辑, 无论函数/方法是否执行成功
  3. afterReturning: 在函数/方法执行成功后调用指定逻辑
  4. afterThrowing: 在方法抛出异常后调用指定逻辑
  5. around: 在函数/方法调用之前和调用之后执行自定义的指定逻辑

切点(PointCut/Matcher)

切点(连接点筛选)功能, 为 string, RegExp, Function 三个类型之一, 指定符合匹配条件的方法才应用特定的通知逻辑

切面(Aspect/Advisor)

切面是通知和切点的结合, 通知和切点共同定义了切面的全部内容 - 是什么, 在何时和何处完成功能.

Advisor={// 切点/匹配器, 为字符串,正则,函数三种, 见 PointCut/Matchermatcher: Matcher,// 通知对象, 拥有 before, afterReturning, afterThrowing, after, around 中一个或多个方法advices: {before(...args){/* ... */},after(){/* ... */},afterReturning(returnValue){/* ... */},afterThrowing(){/* ... */},around(joinPoint){/* ... */}}}

安装

node

npm install uaop

Browser global

<scriptsrc="path/uaop/dist/bundle.js"></script>

模块环境

import*asaopfrom'uaop';// es6// var aop = require('uaop'); // AMD/CMD// window.uaop // global

快速使用

import*asaopfrom'uaop';// es6functiondoSomething(){console.log('doSomething');}functionbeforeAdvice{console.log('before doSomething');}// 函数拦截letproxyFunc=aop.before(doSomething,beforeAdvice);proxyFunc();// 对象拦截letobj={doSomething};letproxyObj=aop.before(obj,'doSomething',beforeAdvice);proxyObj.doSomething();// 类拦截classDo{doSomething(){console.log('doSomething');}}letProxyClass=aop.before(Do,'doSomething',beforeAdvice);letinstance=newProxyClass();instance.doSomething();

API

Function API

提供针对函数执行拦截的API

before(functionToAdvise, beforeFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数执行前, 执行 beforeFunction, beforeFunction 接收与 functionToAdvise 一致的参数

除非抛异常, 否则不会中断函数的执行

varfunctionToAdvise=function(){console.log('functionToAdvise exec');};varadvisedFunction=aop.before(functionToAdvise,function(){console.log('arguments length:',argument.length);});// log:// arguments length: 3// functionToAdvise execadvisedFunction(1,2,3);

afterReturning(functionToAdvise, afterReturningFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数正常返回后, 执行 afterReturningFunction, afterReturningFunction 接收 functionToAdvise 执行后的返回结果作为唯一参数, 不影响返回结果.

varfunctionToAdvise=function(){console.log('functionToAdvise exec');return'functionToAdvise';};varadvisedFunction=aop.afterReturning(functionToAdvise,function(returnValue){console.log('return value: ',returnValue);});// log:// functionToAdvise exec// return value: functionToAdviseadvisedFunction();

afterThrowing(functionToAdvise, afterThrowingFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数抛出异常时, 执行 afterThrowingFunction, afterThrowingFunction 接收 functionToAdvise 抛出的异常对象作为唯一参数.

通知不会吞噬原有异常, 会在 afterThrowingFunction 执行完毕后, 抛出原有异常

varfunctionToAdvise=function(throwError){console.log('functionToAdvise exec');if(throwError){thrownewError('functionToAdvise error');}};varadvisedFunction=aop.afterThrowing(functionToAdvise,function(e){console.log('execption: ',e.message);});// log:// functionToAdvise execadvisedFunction();// log:// functionToAdvise exec// execption: functionToAdvise erroradvisedFunction(true);

after(functionToAdvise, afterFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数正常返回或抛出异常时, 执行 afterFunction

通知不会吞噬原有异常, 会在 afterFunction 执行完毕后, 抛出原有异常

varfunctionToAdvise=function(throwError){if(throwError){console.log('functionToAdvise exception');thrownewError('error');}console.log('functionToAdvise normal exec');};varadvisedFunction=aop.after(functionToAdvise,function(){console.log('after functionToAdvise');});// log:// functionToAdvise normal exec// after functionToAdviseadvisedFunction();// log:// functionToAdvise exception// after functionToAdviseadvisedFunction(true);

around(functionToAdvise, aroundFunction)

返回一个新的函数, 执行逻辑为, 执行 aroundFunction, aroundFunction 接收一个 ProceedingJoinPoint 对象作为参数, 调用其 proceed/proceedApply 方法将执行 functionToAdvise.

varfunctionToAdvise=function(){console.log('functionToAdvise exec arguments: ',[].slice.call(arguments,0));return'functionToAdvise return value';};varadvisedFunction=aop.around(functionToAdvise,function(joinPoint){console.log('before functionToAdvise exec');// proceed/proceddApply 可以多次调用, 会多次执行原函数, proceedApply 可以改变 this 和参数信息varresult=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 execadvisedFunction(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 接收匹配方法执行时的参数

除非抛异常, 否则不会中断匹配方法的执行

vartoAdvise={method: function(){console.log('method exec');}};varadvisedObject=aop.before(toAdvise,'method',function(arg){console.log('before method exec');console.log(arg);});// log:// before method exec// a// method execadvisedObject.method('a');// log:// method exectoAdvise.method('a');

afterReturning(objectToAdvise, matcher, afterReturningFunction)

返回一个新的代理对象, 在 matcher 匹配的方法正常执行后, 执行 afterReturningFunction, afterReturningFunction 接收匹配方法执行后的返回结果作为唯一参数, 不影响返回结果.

vartoAdvise={method: function(){console.log('method exec');return'toAdivse method result';}};varadvisedObject=aop.afterReturning(toAdvise,'method',function(returnValue){console.log('return value: ',returnValue);});// log:// method exec// return value: toAdivse method resultadvisedObject.method();

afterThrowing(objectToAdvise, matcher, afterThrowingFunction)

返回一个新的代理对象, 在 matcher 匹配的方法抛出异常后, 执行 afterThrowingFunction, afterThrowingFunction 接收匹配方法抛出的异常对象作为唯一参数.

通知不会吞噬原有异常, 会在 afterThrowingFunction 执行完毕后, 抛出原有异常

vartoAdvise={method: function(throwError){console.log('method exec');if(throwError){thrownewError('method error');}}};varadvisedObject=aop.afterThrowing(toAdvise,'method',function(e){console.log('execption: ',e.message);});// log:// method execadvisedObject.method();// log:// method exec// execption: method erroradvisedObject.method(true);

after(objectToAdvise, matcher, afterFunction)

返回一个新的代理对象, 在 matcher 匹配的方法正常返回或抛出异常后, 执行 afterFunction。

通知不会吞噬原有异常, 会在 afterFunction 执行完毕后, 抛出原有异常

vartoAdvise={method: function(throwError){if(throwError){console.log('method exception');thrownewError('error');}console.log('method exec');}};varadvisedObject=aop.after(toAdvise,'method',function(){console.log('after method exec');});// log:// method exec// after method execadvisedObject.method();// log:// method exception// after method execadvisedObject.method(true);

around(objectToAdvise, matcher, aroundFunction)

返回一个新的代理对象, 在 matcher 匹配的方法执行时, 执行 aroundFunction, aroundFunction 接收一个 ProceedingJoinPoint 对象作为参数, 调用其 proceed/proceedApply 方法将执行原方法.

vartoAdvise={method: function(){console.log('method exec arguments: ',[].slice.call(arguments,0));return'method return value';}};varadvisedObject=aop.around(toAdvise,'method',function(joinPoint){console.log('before method exec');// proceed/proceedApply 可以多次调用, 会多次执行原方法, proceedApply 可以改变 this 和参数信息varresult=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 execadvisedObject.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 则表示匹配成功。
vartoAdvise={method: function(){},foo: function(){},foo1: function(){},foo2: function(){},init: function(){}};// 将拦截 toAdvise.methodvaradvisedObject=aop.before(toAdvise,'method',function(){});// 将拦截 toAdvise.foo, toAdvise.foo1, toAdvise.foo2varadvisedObject=aop.before(toAdvise,/^foo/,function(){});varfnMatcher=function(obj,name){returnname!=='init';};// 将拦截 toAdvise.foo, toAdvise.foo1, toAdvise.foo2, toAdvise.methodvaradvisedObject=aop.before(toAdvise,fnMatcher,function(){});

Class Method API

提供针对Class方法拦截的 API

createClassProxy(Class, matcher, advices)

创建一个组装了通知行为的类代理, 会重写符合匹配规则的方法, 织入通知逻辑.

advice 拥有 before, afterReturning, afterThrowing, after, around 中一个或多个方法的对象.

About

Aspect oriented programming utilities

Resources

Stars

12 stars

Watchers

10 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - ecomfe/aop: Aspect oriented programming utilities · GitHub
Skip to content

Repository files navigation

Unnamed AOP

一个 js 版的 aop 库, 能够无入侵的增加和改变函数或方法的行为.

基本概念

通知(Advice)

在函数/方法执行的特定时机执行指定的逻辑. 主要有以下几个类型的通知:

  1. before: 在函数/方法执行前调用指定逻辑
  2. after: 在函数/方法执行后调用指定逻辑, 无论函数/方法是否执行成功
  3. afterReturning: 在函数/方法执行成功后调用指定逻辑
  4. afterThrowing: 在方法抛出异常后调用指定逻辑
  5. around: 在函数/方法调用之前和调用之后执行自定义的指定逻辑

切点(PointCut/Matcher)

切点(连接点筛选)功能, 为 string, RegExp, Function 三个类型之一, 指定符合匹配条件的方法才应用特定的通知逻辑

切面(Aspect/Advisor)

切面是通知和切点的结合, 通知和切点共同定义了切面的全部内容 - 是什么, 在何时和何处完成功能.

Advisor={// 切点/匹配器, 为字符串,正则,函数三种, 见 PointCut/Matchermatcher: Matcher,// 通知对象, 拥有 before, afterReturning, afterThrowing, after, around 中一个或多个方法advices: {before(...args){/* ... */},after(){/* ... */},afterReturning(returnValue){/* ... */},afterThrowing(){/* ... */},around(joinPoint){/* ... */}}}

安装

node

npm install uaop

Browser global

<scriptsrc="path/uaop/dist/bundle.js"></script>

模块环境

import*asaopfrom'uaop';// es6// var aop = require('uaop'); // AMD/CMD// window.uaop // global

快速使用

import*asaopfrom'uaop';// es6functiondoSomething(){console.log('doSomething');}functionbeforeAdvice{console.log('before doSomething');}// 函数拦截letproxyFunc=aop.before(doSomething,beforeAdvice);proxyFunc();// 对象拦截letobj={doSomething};letproxyObj=aop.before(obj,'doSomething',beforeAdvice);proxyObj.doSomething();// 类拦截classDo{doSomething(){console.log('doSomething');}}letProxyClass=aop.before(Do,'doSomething',beforeAdvice);letinstance=newProxyClass();instance.doSomething();

API

Function API

提供针对函数执行拦截的API

before(functionToAdvise, beforeFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数执行前, 执行 beforeFunction, beforeFunction 接收与 functionToAdvise 一致的参数

除非抛异常, 否则不会中断函数的执行

varfunctionToAdvise=function(){console.log('functionToAdvise exec');};varadvisedFunction=aop.before(functionToAdvise,function(){console.log('arguments length:',argument.length);});// log:// arguments length: 3// functionToAdvise execadvisedFunction(1,2,3);

afterReturning(functionToAdvise, afterReturningFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数正常返回后, 执行 afterReturningFunction, afterReturningFunction 接收 functionToAdvise 执行后的返回结果作为唯一参数, 不影响返回结果.

varfunctionToAdvise=function(){console.log('functionToAdvise exec');return'functionToAdvise';};varadvisedFunction=aop.afterReturning(functionToAdvise,function(returnValue){console.log('return value: ',returnValue);});// log:// functionToAdvise exec// return value: functionToAdviseadvisedFunction();

afterThrowing(functionToAdvise, afterThrowingFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数抛出异常时, 执行 afterThrowingFunction, afterThrowingFunction 接收 functionToAdvise 抛出的异常对象作为唯一参数.

通知不会吞噬原有异常, 会在 afterThrowingFunction 执行完毕后, 抛出原有异常

varfunctionToAdvise=function(throwError){console.log('functionToAdvise exec');if(throwError){thrownewError('functionToAdvise error');}};varadvisedFunction=aop.afterThrowing(functionToAdvise,function(e){console.log('execption: ',e.message);});// log:// functionToAdvise execadvisedFunction();// log:// functionToAdvise exec// execption: functionToAdvise erroradvisedFunction(true);

after(functionToAdvise, afterFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数正常返回或抛出异常时, 执行 afterFunction

通知不会吞噬原有异常, 会在 afterFunction 执行完毕后, 抛出原有异常

varfunctionToAdvise=function(throwError){if(throwError){console.log('functionToAdvise exception');thrownewError('error');}console.log('functionToAdvise normal exec');};varadvisedFunction=aop.after(functionToAdvise,function(){console.log('after functionToAdvise');});// log:// functionToAdvise normal exec// after functionToAdviseadvisedFunction();// log:// functionToAdvise exception// after functionToAdviseadvisedFunction(true);

around(functionToAdvise, aroundFunction)

返回一个新的函数, 执行逻辑为, 执行 aroundFunction, aroundFunction 接收一个 ProceedingJoinPoint 对象作为参数, 调用其 proceed/proceedApply 方法将执行 functionToAdvise.

varfunctionToAdvise=function(){console.log('functionToAdvise exec arguments: ',[].slice.call(arguments,0));return'functionToAdvise return value';};varadvisedFunction=aop.around(functionToAdvise,function(joinPoint){console.log('before functionToAdvise exec');// proceed/proceddApply 可以多次调用, 会多次执行原函数, proceedApply 可以改变 this 和参数信息varresult=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 execadvisedFunction(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 接收匹配方法执行时的参数

除非抛异常, 否则不会中断匹配方法的执行

vartoAdvise={method: function(){console.log('method exec');}};varadvisedObject=aop.before(toAdvise,'method',function(arg){console.log('before method exec');console.log(arg);});// log:// before method exec// a// method execadvisedObject.method('a');// log:// method exectoAdvise.method('a');

afterReturning(objectToAdvise, matcher, afterReturningFunction)

返回一个新的代理对象, 在 matcher 匹配的方法正常执行后, 执行 afterReturningFunction, afterReturningFunction 接收匹配方法执行后的返回结果作为唯一参数, 不影响返回结果.

vartoAdvise={method: function(){console.log('method exec');return'toAdivse method result';}};varadvisedObject=aop.afterReturning(toAdvise,'method',function(returnValue){console.log('return value: ',returnValue);});// log:// method exec// return value: toAdivse method resultadvisedObject.method();

afterThrowing(objectToAdvise, matcher, afterThrowingFunction)

返回一个新的代理对象, 在 matcher 匹配的方法抛出异常后, 执行 afterThrowingFunction, afterThrowingFunction 接收匹配方法抛出的异常对象作为唯一参数.

通知不会吞噬原有异常, 会在 afterThrowingFunction 执行完毕后, 抛出原有异常

vartoAdvise={method: function(throwError){console.log('method exec');if(throwError){thrownewError('method error');}}};varadvisedObject=aop.afterThrowing(toAdvise,'method',function(e){console.log('execption: ',e.message);});// log:// method execadvisedObject.method();// log:// method exec// execption: method erroradvisedObject.method(true);

after(objectToAdvise, matcher, afterFunction)

返回一个新的代理对象, 在 matcher 匹配的方法正常返回或抛出异常后, 执行 afterFunction。

通知不会吞噬原有异常, 会在 afterFunction 执行完毕后, 抛出原有异常

vartoAdvise={method: function(throwError){if(throwError){console.log('method exception');thrownewError('error');}console.log('method exec');}};varadvisedObject=aop.after(toAdvise,'method',function(){console.log('after method exec');});// log:// method exec// after method execadvisedObject.method();// log:// method exception// after method execadvisedObject.method(true);

around(objectToAdvise, matcher, aroundFunction)

返回一个新的代理对象, 在 matcher 匹配的方法执行时, 执行 aroundFunction, aroundFunction 接收一个 ProceedingJoinPoint 对象作为参数, 调用其 proceed/proceedApply 方法将执行原方法.

vartoAdvise={method: function(){console.log('method exec arguments: ',[].slice.call(arguments,0));return'method return value';}};varadvisedObject=aop.around(toAdvise,'method',function(joinPoint){console.log('before method exec');// proceed/proceedApply 可以多次调用, 会多次执行原方法, proceedApply 可以改变 this 和参数信息varresult=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 execadvisedObject.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 则表示匹配成功。
vartoAdvise={method: function(){},foo: function(){},foo1: function(){},foo2: function(){},init: function(){}};// 将拦截 toAdvise.methodvaradvisedObject=aop.before(toAdvise,'method',function(){});// 将拦截 toAdvise.foo, toAdvise.foo1, toAdvise.foo2varadvisedObject=aop.before(toAdvise,/^foo/,function(){});varfnMatcher=function(obj,name){returnname!=='init';};// 将拦截 toAdvise.foo, toAdvise.foo1, toAdvise.foo2, toAdvise.methodvaradvisedObject=aop.before(toAdvise,fnMatcher,function(){});

Class Method API

提供针对Class方法拦截的 API

createClassProxy(Class, matcher, advices)

创建一个组装了通知行为的类代理, 会重写符合匹配规则的方法, 织入通知逻辑.

advice 拥有 before, afterReturning, afterThrowing, after, around 中一个或多个方法的对象.

About

Aspect oriented programming utilities

Resources

Stars

12 stars

Watchers

10 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - ecomfe/aop: Aspect oriented programming utilities · GitHub
Skip to content

Repository files navigation

Unnamed AOP

一个 js 版的 aop 库, 能够无入侵的增加和改变函数或方法的行为.

基本概念

通知(Advice)

在函数/方法执行的特定时机执行指定的逻辑. 主要有以下几个类型的通知:

  1. before: 在函数/方法执行前调用指定逻辑
  2. after: 在函数/方法执行后调用指定逻辑, 无论函数/方法是否执行成功
  3. afterReturning: 在函数/方法执行成功后调用指定逻辑
  4. afterThrowing: 在方法抛出异常后调用指定逻辑
  5. around: 在函数/方法调用之前和调用之后执行自定义的指定逻辑

切点(PointCut/Matcher)

切点(连接点筛选)功能, 为 string, RegExp, Function 三个类型之一, 指定符合匹配条件的方法才应用特定的通知逻辑

切面(Aspect/Advisor)

切面是通知和切点的结合, 通知和切点共同定义了切面的全部内容 - 是什么, 在何时和何处完成功能.

Advisor={// 切点/匹配器, 为字符串,正则,函数三种, 见 PointCut/Matchermatcher: Matcher,// 通知对象, 拥有 before, afterReturning, afterThrowing, after, around 中一个或多个方法advices: {before(...args){/* ... */},after(){/* ... */},afterReturning(returnValue){/* ... */},afterThrowing(){/* ... */},around(joinPoint){/* ... */}}}

安装

node

npm install uaop

Browser global

<scriptsrc="path/uaop/dist/bundle.js"></script>

模块环境

import*asaopfrom'uaop';// es6// var aop = require('uaop'); // AMD/CMD// window.uaop // global

快速使用

import*asaopfrom'uaop';// es6functiondoSomething(){console.log('doSomething');}functionbeforeAdvice{console.log('before doSomething');}// 函数拦截letproxyFunc=aop.before(doSomething,beforeAdvice);proxyFunc();// 对象拦截letobj={doSomething};letproxyObj=aop.before(obj,'doSomething',beforeAdvice);proxyObj.doSomething();// 类拦截classDo{doSomething(){console.log('doSomething');}}letProxyClass=aop.before(Do,'doSomething',beforeAdvice);letinstance=newProxyClass();instance.doSomething();

API

Function API

提供针对函数执行拦截的API

before(functionToAdvise, beforeFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数执行前, 执行 beforeFunction, beforeFunction 接收与 functionToAdvise 一致的参数

除非抛异常, 否则不会中断函数的执行

varfunctionToAdvise=function(){console.log('functionToAdvise exec');};varadvisedFunction=aop.before(functionToAdvise,function(){console.log('arguments length:',argument.length);});// log:// arguments length: 3// functionToAdvise execadvisedFunction(1,2,3);

afterReturning(functionToAdvise, afterReturningFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数正常返回后, 执行 afterReturningFunction, afterReturningFunction 接收 functionToAdvise 执行后的返回结果作为唯一参数, 不影响返回结果.

varfunctionToAdvise=function(){console.log('functionToAdvise exec');return'functionToAdvise';};varadvisedFunction=aop.afterReturning(functionToAdvise,function(returnValue){console.log('return value: ',returnValue);});// log:// functionToAdvise exec// return value: functionToAdviseadvisedFunction();

afterThrowing(functionToAdvise, afterThrowingFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数抛出异常时, 执行 afterThrowingFunction, afterThrowingFunction 接收 functionToAdvise 抛出的异常对象作为唯一参数.

通知不会吞噬原有异常, 会在 afterThrowingFunction 执行完毕后, 抛出原有异常

varfunctionToAdvise=function(throwError){console.log('functionToAdvise exec');if(throwError){thrownewError('functionToAdvise error');}};varadvisedFunction=aop.afterThrowing(functionToAdvise,function(e){console.log('execption: ',e.message);});// log:// functionToAdvise execadvisedFunction();// log:// functionToAdvise exec// execption: functionToAdvise erroradvisedFunction(true);

after(functionToAdvise, afterFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数正常返回或抛出异常时, 执行 afterFunction

通知不会吞噬原有异常, 会在 afterFunction 执行完毕后, 抛出原有异常

varfunctionToAdvise=function(throwError){if(throwError){console.log('functionToAdvise exception');thrownewError('error');}console.log('functionToAdvise normal exec');};varadvisedFunction=aop.after(functionToAdvise,function(){console.log('after functionToAdvise');});// log:// functionToAdvise normal exec// after functionToAdviseadvisedFunction();// log:// functionToAdvise exception// after functionToAdviseadvisedFunction(true);

around(functionToAdvise, aroundFunction)

返回一个新的函数, 执行逻辑为, 执行 aroundFunction, aroundFunction 接收一个 ProceedingJoinPoint 对象作为参数, 调用其 proceed/proceedApply 方法将执行 functionToAdvise.

varfunctionToAdvise=function(){console.log('functionToAdvise exec arguments: ',[].slice.call(arguments,0));return'functionToAdvise return value';};varadvisedFunction=aop.around(functionToAdvise,function(joinPoint){console.log('before functionToAdvise exec');// proceed/proceddApply 可以多次调用, 会多次执行原函数, proceedApply 可以改变 this 和参数信息varresult=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 execadvisedFunction(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 接收匹配方法执行时的参数

除非抛异常, 否则不会中断匹配方法的执行

vartoAdvise={method: function(){console.log('method exec');}};varadvisedObject=aop.before(toAdvise,'method',function(arg){console.log('before method exec');console.log(arg);});// log:// before method exec// a// method execadvisedObject.method('a');// log:// method exectoAdvise.method('a');

afterReturning(objectToAdvise, matcher, afterReturningFunction)

返回一个新的代理对象, 在 matcher 匹配的方法正常执行后, 执行 afterReturningFunction, afterReturningFunction 接收匹配方法执行后的返回结果作为唯一参数, 不影响返回结果.

vartoAdvise={method: function(){console.log('method exec');return'toAdivse method result';}};varadvisedObject=aop.afterReturning(toAdvise,'method',function(returnValue){console.log('return value: ',returnValue);});// log:// method exec// return value: toAdivse method resultadvisedObject.method();

afterThrowing(objectToAdvise, matcher, afterThrowingFunction)

返回一个新的代理对象, 在 matcher 匹配的方法抛出异常后, 执行 afterThrowingFunction, afterThrowingFunction 接收匹配方法抛出的异常对象作为唯一参数.

通知不会吞噬原有异常, 会在 afterThrowingFunction 执行完毕后, 抛出原有异常

vartoAdvise={method: function(throwError){console.log('method exec');if(throwError){thrownewError('method error');}}};varadvisedObject=aop.afterThrowing(toAdvise,'method',function(e){console.log('execption: ',e.message);});// log:// method execadvisedObject.method();// log:// method exec// execption: method erroradvisedObject.method(true);

after(objectToAdvise, matcher, afterFunction)

返回一个新的代理对象, 在 matcher 匹配的方法正常返回或抛出异常后, 执行 afterFunction。

通知不会吞噬原有异常, 会在 afterFunction 执行完毕后, 抛出原有异常

vartoAdvise={method: function(throwError){if(throwError){console.log('method exception');thrownewError('error');}console.log('method exec');}};varadvisedObject=aop.after(toAdvise,'method',function(){console.log('after method exec');});// log:// method exec// after method execadvisedObject.method();// log:// method exception// after method execadvisedObject.method(true);

around(objectToAdvise, matcher, aroundFunction)

返回一个新的代理对象, 在 matcher 匹配的方法执行时, 执行 aroundFunction, aroundFunction 接收一个 ProceedingJoinPoint 对象作为参数, 调用其 proceed/proceedApply 方法将执行原方法.

vartoAdvise={method: function(){console.log('method exec arguments: ',[].slice.call(arguments,0));return'method return value';}};varadvisedObject=aop.around(toAdvise,'method',function(joinPoint){console.log('before method exec');// proceed/proceedApply 可以多次调用, 会多次执行原方法, proceedApply 可以改变 this 和参数信息varresult=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 execadvisedObject.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 则表示匹配成功。
vartoAdvise={method: function(){},foo: function(){},foo1: function(){},foo2: function(){},init: function(){}};// 将拦截 toAdvise.methodvaradvisedObject=aop.before(toAdvise,'method',function(){});// 将拦截 toAdvise.foo, toAdvise.foo1, toAdvise.foo2varadvisedObject=aop.before(toAdvise,/^foo/,function(){});varfnMatcher=function(obj,name){returnname!=='init';};// 将拦截 toAdvise.foo, toAdvise.foo1, toAdvise.foo2, toAdvise.methodvaradvisedObject=aop.before(toAdvise,fnMatcher,function(){});

Class Method API

提供针对Class方法拦截的 API

createClassProxy(Class, matcher, advices)

创建一个组装了通知行为的类代理, 会重写符合匹配规则的方法, 织入通知逻辑.

advice 拥有 before, afterReturning, afterThrowing, after, around 中一个或多个方法的对象.

About

Aspect oriented programming utilities

Resources

Stars

12 stars

Watchers

10 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - ecomfe/aop: Aspect oriented programming utilities · GitHub
Skip to content

Repository files navigation

Unnamed AOP

一个 js 版的 aop 库, 能够无入侵的增加和改变函数或方法的行为.

基本概念

通知(Advice)

在函数/方法执行的特定时机执行指定的逻辑. 主要有以下几个类型的通知:

  1. before: 在函数/方法执行前调用指定逻辑
  2. after: 在函数/方法执行后调用指定逻辑, 无论函数/方法是否执行成功
  3. afterReturning: 在函数/方法执行成功后调用指定逻辑
  4. afterThrowing: 在方法抛出异常后调用指定逻辑
  5. around: 在函数/方法调用之前和调用之后执行自定义的指定逻辑

切点(PointCut/Matcher)

切点(连接点筛选)功能, 为 string, RegExp, Function 三个类型之一, 指定符合匹配条件的方法才应用特定的通知逻辑

切面(Aspect/Advisor)

切面是通知和切点的结合, 通知和切点共同定义了切面的全部内容 - 是什么, 在何时和何处完成功能.

Advisor={// 切点/匹配器, 为字符串,正则,函数三种, 见 PointCut/Matchermatcher: Matcher,// 通知对象, 拥有 before, afterReturning, afterThrowing, after, around 中一个或多个方法advices: {before(...args){/* ... */},after(){/* ... */},afterReturning(returnValue){/* ... */},afterThrowing(){/* ... */},around(joinPoint){/* ... */}}}

安装

node

npm install uaop

Browser global

<scriptsrc="path/uaop/dist/bundle.js"></script>

模块环境

import*asaopfrom'uaop';// es6// var aop = require('uaop'); // AMD/CMD// window.uaop // global

快速使用

import*asaopfrom'uaop';// es6functiondoSomething(){console.log('doSomething');}functionbeforeAdvice{console.log('before doSomething');}// 函数拦截letproxyFunc=aop.before(doSomething,beforeAdvice);proxyFunc();// 对象拦截letobj={doSomething};letproxyObj=aop.before(obj,'doSomething',beforeAdvice);proxyObj.doSomething();// 类拦截classDo{doSomething(){console.log('doSomething');}}letProxyClass=aop.before(Do,'doSomething',beforeAdvice);letinstance=newProxyClass();instance.doSomething();

API

Function API

提供针对函数执行拦截的API

before(functionToAdvise, beforeFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数执行前, 执行 beforeFunction, beforeFunction 接收与 functionToAdvise 一致的参数

除非抛异常, 否则不会中断函数的执行

varfunctionToAdvise=function(){console.log('functionToAdvise exec');};varadvisedFunction=aop.before(functionToAdvise,function(){console.log('arguments length:',argument.length);});// log:// arguments length: 3// functionToAdvise execadvisedFunction(1,2,3);

afterReturning(functionToAdvise, afterReturningFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数正常返回后, 执行 afterReturningFunction, afterReturningFunction 接收 functionToAdvise 执行后的返回结果作为唯一参数, 不影响返回结果.

varfunctionToAdvise=function(){console.log('functionToAdvise exec');return'functionToAdvise';};varadvisedFunction=aop.afterReturning(functionToAdvise,function(returnValue){console.log('return value: ',returnValue);});// log:// functionToAdvise exec// return value: functionToAdviseadvisedFunction();

afterThrowing(functionToAdvise, afterThrowingFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数抛出异常时, 执行 afterThrowingFunction, afterThrowingFunction 接收 functionToAdvise 抛出的异常对象作为唯一参数.

通知不会吞噬原有异常, 会在 afterThrowingFunction 执行完毕后, 抛出原有异常

varfunctionToAdvise=function(throwError){console.log('functionToAdvise exec');if(throwError){thrownewError('functionToAdvise error');}};varadvisedFunction=aop.afterThrowing(functionToAdvise,function(e){console.log('execption: ',e.message);});// log:// functionToAdvise execadvisedFunction();// log:// functionToAdvise exec// execption: functionToAdvise erroradvisedFunction(true);

after(functionToAdvise, afterFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数正常返回或抛出异常时, 执行 afterFunction

通知不会吞噬原有异常, 会在 afterFunction 执行完毕后, 抛出原有异常

varfunctionToAdvise=function(throwError){if(throwError){console.log('functionToAdvise exception');thrownewError('error');}console.log('functionToAdvise normal exec');};varadvisedFunction=aop.after(functionToAdvise,function(){console.log('after functionToAdvise');});// log:// functionToAdvise normal exec// after functionToAdviseadvisedFunction();// log:// functionToAdvise exception// after functionToAdviseadvisedFunction(true);

around(functionToAdvise, aroundFunction)

返回一个新的函数, 执行逻辑为, 执行 aroundFunction, aroundFunction 接收一个 ProceedingJoinPoint 对象作为参数, 调用其 proceed/proceedApply 方法将执行 functionToAdvise.

varfunctionToAdvise=function(){console.log('functionToAdvise exec arguments: ',[].slice.call(arguments,0));return'functionToAdvise return value';};varadvisedFunction=aop.around(functionToAdvise,function(joinPoint){console.log('before functionToAdvise exec');// proceed/proceddApply 可以多次调用, 会多次执行原函数, proceedApply 可以改变 this 和参数信息varresult=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 execadvisedFunction(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 接收匹配方法执行时的参数

除非抛异常, 否则不会中断匹配方法的执行

vartoAdvise={method: function(){console.log('method exec');}};varadvisedObject=aop.before(toAdvise,'method',function(arg){console.log('before method exec');console.log(arg);});// log:// before method exec// a// method execadvisedObject.method('a');// log:// method exectoAdvise.method('a');

afterReturning(objectToAdvise, matcher, afterReturningFunction)

返回一个新的代理对象, 在 matcher 匹配的方法正常执行后, 执行 afterReturningFunction, afterReturningFunction 接收匹配方法执行后的返回结果作为唯一参数, 不影响返回结果.

vartoAdvise={method: function(){console.log('method exec');return'toAdivse method result';}};varadvisedObject=aop.afterReturning(toAdvise,'method',function(returnValue){console.log('return value: ',returnValue);});// log:// method exec// return value: toAdivse method resultadvisedObject.method();

afterThrowing(objectToAdvise, matcher, afterThrowingFunction)

返回一个新的代理对象, 在 matcher 匹配的方法抛出异常后, 执行 afterThrowingFunction, afterThrowingFunction 接收匹配方法抛出的异常对象作为唯一参数.

通知不会吞噬原有异常, 会在 afterThrowingFunction 执行完毕后, 抛出原有异常

vartoAdvise={method: function(throwError){console.log('method exec');if(throwError){thrownewError('method error');}}};varadvisedObject=aop.afterThrowing(toAdvise,'method',function(e){console.log('execption: ',e.message);});// log:// method execadvisedObject.method();// log:// method exec// execption: method erroradvisedObject.method(true);

after(objectToAdvise, matcher, afterFunction)

返回一个新的代理对象, 在 matcher 匹配的方法正常返回或抛出异常后, 执行 afterFunction。

通知不会吞噬原有异常, 会在 afterFunction 执行完毕后, 抛出原有异常

vartoAdvise={method: function(throwError){if(throwError){console.log('method exception');thrownewError('error');}console.log('method exec');}};varadvisedObject=aop.after(toAdvise,'method',function(){console.log('after method exec');});// log:// method exec// after method execadvisedObject.method();// log:// method exception// after method execadvisedObject.method(true);

around(objectToAdvise, matcher, aroundFunction)

返回一个新的代理对象, 在 matcher 匹配的方法执行时, 执行 aroundFunction, aroundFunction 接收一个 ProceedingJoinPoint 对象作为参数, 调用其 proceed/proceedApply 方法将执行原方法.

vartoAdvise={method: function(){console.log('method exec arguments: ',[].slice.call(arguments,0));return'method return value';}};varadvisedObject=aop.around(toAdvise,'method',function(joinPoint){console.log('before method exec');// proceed/proceedApply 可以多次调用, 会多次执行原方法, proceedApply 可以改变 this 和参数信息varresult=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 execadvisedObject.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 则表示匹配成功。
vartoAdvise={method: function(){},foo: function(){},foo1: function(){},foo2: function(){},init: function(){}};// 将拦截 toAdvise.methodvaradvisedObject=aop.before(toAdvise,'method',function(){});// 将拦截 toAdvise.foo, toAdvise.foo1, toAdvise.foo2varadvisedObject=aop.before(toAdvise,/^foo/,function(){});varfnMatcher=function(obj,name){returnname!=='init';};// 将拦截 toAdvise.foo, toAdvise.foo1, toAdvise.foo2, toAdvise.methodvaradvisedObject=aop.before(toAdvise,fnMatcher,function(){});

Class Method API

提供针对Class方法拦截的 API

createClassProxy(Class, matcher, advices)

创建一个组装了通知行为的类代理, 会重写符合匹配规则的方法, 织入通知逻辑.

advice 拥有 before, afterReturning, afterThrowing, after, around 中一个或多个方法的对象.

About

Aspect oriented programming utilities

Resources

Stars

12 stars

Watchers

10 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); GitHub - ecomfe/aop: Aspect oriented programming utilities · GitHub
Skip to content

Repository files navigation

Unnamed AOP

一个 js 版的 aop 库, 能够无入侵的增加和改变函数或方法的行为.

基本概念

通知(Advice)

在函数/方法执行的特定时机执行指定的逻辑. 主要有以下几个类型的通知:

  1. before: 在函数/方法执行前调用指定逻辑
  2. after: 在函数/方法执行后调用指定逻辑, 无论函数/方法是否执行成功
  3. afterReturning: 在函数/方法执行成功后调用指定逻辑
  4. afterThrowing: 在方法抛出异常后调用指定逻辑
  5. around: 在函数/方法调用之前和调用之后执行自定义的指定逻辑

切点(PointCut/Matcher)

切点(连接点筛选)功能, 为 string, RegExp, Function 三个类型之一, 指定符合匹配条件的方法才应用特定的通知逻辑

切面(Aspect/Advisor)

切面是通知和切点的结合, 通知和切点共同定义了切面的全部内容 - 是什么, 在何时和何处完成功能.

Advisor={// 切点/匹配器, 为字符串,正则,函数三种, 见 PointCut/Matchermatcher: Matcher,// 通知对象, 拥有 before, afterReturning, afterThrowing, after, around 中一个或多个方法advices: {before(...args){/* ... */},after(){/* ... */},afterReturning(returnValue){/* ... */},afterThrowing(){/* ... */},around(joinPoint){/* ... */}}}

安装

node

npm install uaop

Browser global

<scriptsrc="path/uaop/dist/bundle.js"></script>

模块环境

import*asaopfrom'uaop';// es6// var aop = require('uaop'); // AMD/CMD// window.uaop // global

快速使用

import*asaopfrom'uaop';// es6functiondoSomething(){console.log('doSomething');}functionbeforeAdvice{console.log('before doSomething');}// 函数拦截letproxyFunc=aop.before(doSomething,beforeAdvice);proxyFunc();// 对象拦截letobj={doSomething};letproxyObj=aop.before(obj,'doSomething',beforeAdvice);proxyObj.doSomething();// 类拦截classDo{doSomething(){console.log('doSomething');}}letProxyClass=aop.before(Do,'doSomething',beforeAdvice);letinstance=newProxyClass();instance.doSomething();

API

Function API

提供针对函数执行拦截的API

before(functionToAdvise, beforeFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数执行前, 执行 beforeFunction, beforeFunction 接收与 functionToAdvise 一致的参数

除非抛异常, 否则不会中断函数的执行

varfunctionToAdvise=function(){console.log('functionToAdvise exec');};varadvisedFunction=aop.before(functionToAdvise,function(){console.log('arguments length:',argument.length);});// log:// arguments length: 3// functionToAdvise execadvisedFunction(1,2,3);

afterReturning(functionToAdvise, afterReturningFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数正常返回后, 执行 afterReturningFunction, afterReturningFunction 接收 functionToAdvise 执行后的返回结果作为唯一参数, 不影响返回结果.

varfunctionToAdvise=function(){console.log('functionToAdvise exec');return'functionToAdvise';};varadvisedFunction=aop.afterReturning(functionToAdvise,function(returnValue){console.log('return value: ',returnValue);});// log:// functionToAdvise exec// return value: functionToAdviseadvisedFunction();

afterThrowing(functionToAdvise, afterThrowingFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数抛出异常时, 执行 afterThrowingFunction, afterThrowingFunction 接收 functionToAdvise 抛出的异常对象作为唯一参数.

通知不会吞噬原有异常, 会在 afterThrowingFunction 执行完毕后, 抛出原有异常

varfunctionToAdvise=function(throwError){console.log('functionToAdvise exec');if(throwError){thrownewError('functionToAdvise error');}};varadvisedFunction=aop.afterThrowing(functionToAdvise,function(e){console.log('execption: ',e.message);});// log:// functionToAdvise execadvisedFunction();// log:// functionToAdvise exec// execption: functionToAdvise erroradvisedFunction(true);

after(functionToAdvise, afterFunction)

返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数正常返回或抛出异常时, 执行 afterFunction

通知不会吞噬原有异常, 会在 afterFunction 执行完毕后, 抛出原有异常

varfunctionToAdvise=function(throwError){if(throwError){console.log('functionToAdvise exception');thrownewError('error');}console.log('functionToAdvise normal exec');};varadvisedFunction=aop.after(functionToAdvise,function(){console.log('after functionToAdvise');});// log:// functionToAdvise normal exec// after functionToAdviseadvisedFunction();// log:// functionToAdvise exception// after functionToAdviseadvisedFunction(true);

around(functionToAdvise, aroundFunction)

返回一个新的函数, 执行逻辑为, 执行 aroundFunction, aroundFunction 接收一个 ProceedingJoinPoint 对象作为参数, 调用其 proceed/proceedApply 方法将执行 functionToAdvise.

varfunctionToAdvise=function(){console.log('functionToAdvise exec arguments: ',[].slice.call(arguments,0));return'functionToAdvise return value';};varadvisedFunction=aop.around(functionToAdvise,function(joinPoint){console.log('before functionToAdvise exec');// proceed/proceddApply 可以多次调用, 会多次执行原函数, proceedApply 可以改变 this 和参数信息varresult=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 execadvisedFunction(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 接收匹配方法执行时的参数

除非抛异常, 否则不会中断匹配方法的执行

vartoAdvise={method: function(){console.log('method exec');}};varadvisedObject=aop.before(toAdvise,'method',function(arg){console.log('before method exec');console.log(arg);});// log:// before method exec// a// method execadvisedObject.method('a');// log:// method exectoAdvise.method('a');

afterReturning(objectToAdvise, matcher, afterReturningFunction)

返回一个新的代理对象, 在 matcher 匹配的方法正常执行后, 执行 afterReturningFunction, afterReturningFunction 接收匹配方法执行后的返回结果作为唯一参数, 不影响返回结果.

vartoAdvise={method: function(){console.log('method exec');return'toAdivse method result';}};varadvisedObject=aop.afterReturning(toAdvise,'method',function(returnValue){console.log('return value: ',returnValue);});// log:// method exec// return value: toAdivse method resultadvisedObject.method();

afterThrowing(objectToAdvise, matcher, afterThrowingFunction)

返回一个新的代理对象, 在 matcher 匹配的方法抛出异常后, 执行 afterThrowingFunction, afterThrowingFunction 接收匹配方法抛出的异常对象作为唯一参数.

通知不会吞噬原有异常, 会在 afterThrowingFunction 执行完毕后, 抛出原有异常

vartoAdvise={method: function(throwError){console.log('method exec');if(throwError){thrownewError('method error');}}};varadvisedObject=aop.afterThrowing(toAdvise,'method',function(e){console.log('execption: ',e.message);});// log:// method execadvisedObject.method();// log:// method exec// execption: method erroradvisedObject.method(true);

after(objectToAdvise, matcher, afterFunction)

返回一个新的代理对象, 在 matcher 匹配的方法正常返回或抛出异常后, 执行 afterFunction。

通知不会吞噬原有异常, 会在 afterFunction 执行完毕后, 抛出原有异常

vartoAdvise={method: function(throwError){if(throwError){console.log('method exception');thrownewError('error');}console.log('method exec');}};varadvisedObject=aop.after(toAdvise,'method',function(){console.log('after method exec');});// log:// method exec// after method execadvisedObject.method();// log:// method exception// after method execadvisedObject.method(true);

around(objectToAdvise, matcher, aroundFunction)

返回一个新的代理对象, 在 matcher 匹配的方法执行时, 执行 aroundFunction, aroundFunction 接收一个 ProceedingJoinPoint 对象作为参数, 调用其 proceed/proceedApply 方法将执行原方法.

vartoAdvise={method: function(){console.log('method exec arguments: ',[].slice.call(arguments,0));return'method return value';}};varadvisedObject=aop.around(toAdvise,'method',function(joinPoint){console.log('before method exec');// proceed/proceedApply 可以多次调用, 会多次执行原方法, proceedApply 可以改变 this 和参数信息varresult=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 execadvisedObject.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 则表示匹配成功。
vartoAdvise={method: function(){},foo: function(){},foo1: function(){},foo2: function(){},init: function(){}};// 将拦截 toAdvise.methodvaradvisedObject=aop.before(toAdvise,'method',function(){});// 将拦截 toAdvise.foo, toAdvise.foo1, toAdvise.foo2varadvisedObject=aop.before(toAdvise,/^foo/,function(){});varfnMatcher=function(obj,name){returnname!=='init';};// 将拦截 toAdvise.foo, toAdvise.foo1, toAdvise.foo2, toAdvise.methodvaradvisedObject=aop.before(toAdvise,fnMatcher,function(){});

Class Method API

提供针对Class方法拦截的 API

createClassProxy(Class, matcher, advices)

创建一个组装了通知行为的类代理, 会重写符合匹配规则的方法, 织入通知逻辑.

advice 拥有 before, afterReturning, afterThrowing, after, around 中一个或多个方法的对象.

About

Aspect oriented programming utilities

Resources

Stars

12 stars

Watchers

10 watching

Forks

Releases

Packages

Used by

Contributors

Languages