{"id":29926652,"url":"https://github.com/ecomfe/aop","last_synced_at":"2025-08-02T12:43:01.655Z","repository":{"id":57384308,"uuid":"55659283","full_name":"ecomfe/aop","owner":"ecomfe","description":"Aspect oriented programming utilities","archived":false,"fork":false,"pushed_at":"2016-06-12T02:09:34.000Z","size":468,"stargazers_count":12,"open_issues_count":0,"forks_count":1,"subscribers_count":11,"default_branch":"develop","last_synced_at":"2025-06-06T12:07:10.302Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ecomfe.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-04-07T03:05:08.000Z","updated_at":"2021-04-02T00:23:00.000Z","dependencies_parsed_at":"2022-09-04T08:11:51.598Z","dependency_job_id":null,"html_url":"https://github.com/ecomfe/aop","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/ecomfe/aop","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ecomfe%2Faop","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ecomfe%2Faop/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ecomfe%2Faop/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ecomfe%2Faop/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ecomfe","download_url":"https://codeload.github.com/ecomfe/aop/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ecomfe%2Faop/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268392180,"owners_count":24243297,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-02T02:00:12.353Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-08-02T12:42:26.427Z","updated_at":"2025-08-02T12:43:01.614Z","avatar_url":"https://github.com/ecomfe.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"Unnamed AOP\n===\n\n一个 js 版的 aop 库, 能够无入侵的增加和改变函数或方法的行为.\n\n## 基本概念\n\n### [面向切面编程](http://en.wikipedia.org/wiki/Aspect-oriented_programming)\n\n### 通知(Advice)\n\n在函数/方法执行的特定时机执行指定的逻辑. 主要有以下几个类型的通知:\n\n1. before: 在函数/方法执行前调用指定逻辑\n2. after: 在函数/方法执行后调用指定逻辑, 无论函数/方法是否执行成功\n3. afterReturning: 在函数/方法执行成功后调用指定逻辑\n4. afterThrowing: 在方法抛出异常后调用指定逻辑\n5. around: 在函数/方法调用之前和调用之后执行自定义的指定逻辑\n\n### 切点(PointCut/Matcher)\n\n切点（连接点筛选）功能, 为 string, RegExp, Function 三个类型之一, 指定符合匹配条件的方法才应用特定的通知逻辑\n\n### 切面(Aspect/Advisor)\n\n切面是通知和切点的结合, 通知和切点共同定义了切面的全部内容 - 是什么, 在何时和何处完成功能.\n\n```javascript\nAdvisor = {\n    // 切点/匹配器, 为字符串,正则,函数三种, 见 PointCut/Matcher\n    matcher: Matcher,\n\n    // 通知对象, 拥有 before, afterReturning, afterThrowing, after, around 中一个或多个方法\n    advices: {\n       before(...args) { /* ... */},\n       after() { /* ... */ },\n       afterReturning(returnValue) { /* ... */ },\n       afterThrowing() { /* ... */ },\n       around(joinPoint) { /* ... */ }\n    }\n}\n```\n\n## 安装\n\nnode\n\n```shell\nnpm install uaop\n```\nBrowser global\n\n```html\n\u003cscript src=\"path/uaop/dist/bundle.js\"\u003e\u003c/script\u003e\n```\n\n模块环境\n\n```javascript\nimport * as aop from 'uaop'; // es6\n// var aop = require('uaop'); // AMD/CMD\n// window.uaop // global\n```\n\n## 快速使用\n\n```javascript\nimport * as aop from 'uaop'; // es6\n\nfunction doSomething() {\n    console.log('doSomething');\n}\n\nfunction beforeAdvice {\n    console.log('before doSomething');\n}\n\n// 函数拦截\nlet proxyFunc = aop.before(doSomething, beforeAdvice);\n\nproxyFunc();\n\n// 对象拦截\nlet obj = {doSomething};\nlet proxyObj = aop.before(obj, 'doSomething', beforeAdvice);\nproxyObj.doSomething();\n\n\n// 类拦截\nclass Do {\n  doSomething() {\n      console.log('doSomething');\n  }\n}\n\nlet ProxyClass = aop.before(Do, 'doSomething', beforeAdvice);\nlet instance = new ProxyClass();\ninstance.doSomething();\n\n```\n\n## API\n\n### Function API\n\n提供针对函数执行拦截的API\n\n#### before(functionToAdvise, beforeFunction)\n\n返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数执行前, 执行 beforeFunction, beforeFunction 接收与 functionToAdvise 一致的参数\n\n**除非抛异常, 否则不会中断函数的执行**\n\n```javascript\nvar functionToAdvise = function () {\n    console.log('functionToAdvise exec');\n};\nvar advisedFunction = aop.before(functionToAdvise, function () {\n    console.log('arguments length:', argument.length);\n});\n\n// log:\n// arguments length: 3\n// functionToAdvise exec\nadvisedFunction(1, 2, 3);\n```\n\n#### afterReturning(functionToAdvise, afterReturningFunction)\n\n返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数正常返回后, 执行 afterReturningFunction,\nafterReturningFunction 接收 functionToAdvise 执行后的返回结果作为唯一参数, 不影响返回结果.\n\n```javascript\nvar functionToAdvise = function () {\n    console.log('functionToAdvise exec');\n    return 'functionToAdvise';\n};\nvar advisedFunction = aop.afterReturning(functionToAdvise, function (returnValue) {\n    console.log('return value: ', returnValue);\n});\n\n// log:\n// functionToAdvise exec\n// return value: functionToAdvise\nadvisedFunction();\n```\n\n#### afterThrowing(functionToAdvise, afterThrowingFunction)\n\n返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数抛出异常时, 执行 afterThrowingFunction,\nafterThrowingFunction 接收 functionToAdvise 抛出的异常对象作为唯一参数.\n\n**通知不会吞噬原有异常, 会在 afterThrowingFunction 执行完毕后, 抛出原有异常**\n\n```javascript\nvar functionToAdvise = function (throwError) {\n    console.log('functionToAdvise exec');\n    if(throwError) {\n        throw new Error('functionToAdvise error');\n    }\n};\nvar advisedFunction = aop.afterThrowing(functionToAdvise, function (e) {\n    console.log('execption: ', e.message);\n});\n\n// log:\n// functionToAdvise exec\nadvisedFunction();\n\n// log:\n// functionToAdvise exec\n// execption: functionToAdvise error\nadvisedFunction(true);\n```\n\n#### after(functionToAdvise, afterFunction)\n\n返回一个新的函数, 执行逻辑为, 在 functionToAdvise 函数正常返回或抛出异常时, 执行 afterFunction\n\n**通知不会吞噬原有异常, 会在 afterFunction 执行完毕后, 抛出原有异常**\n\n```javascript\nvar functionToAdvise = function (throwError) {\n    if(throwError) {\n        console.log('functionToAdvise exception');\n        throw new Error('error');\n    }\n\n    console.log('functionToAdvise normal exec');\n};\nvar advisedFunction = aop.after(functionToAdvise, function () {\n    console.log('after functionToAdvise');\n});\n\n// log:\n// functionToAdvise normal exec\n// after functionToAdvise\nadvisedFunction();\n\n// log:\n// functionToAdvise exception\n// after functionToAdvise\nadvisedFunction(true);\n```\n\n#### around(functionToAdvise, aroundFunction)\n\n返回一个新的函数, 执行逻辑为, 执行 aroundFunction, aroundFunction 接收一个 ProceedingJoinPoint 对象作为参数,\n调用其 proceed/proceedApply 方法将执行 functionToAdvise.\n\n```javascript\nvar functionToAdvise = function () {\n    console.log('functionToAdvise exec arguments: ', [].slice.call(arguments, 0));\n    return 'functionToAdvise return value';\n};\nvar advisedFunction = aop.around(functionToAdvise, function (joinPoint) {\n    console.log('before functionToAdvise exec');\n    // proceed/proceddApply 可以多次调用, 会多次执行原函数, proceedApply 可以改变 this 和参数信息\n    var result = joinPoint.proceed();\n    result = joinPoint.proceedApply(null, [1, 2]);\n    console.log('functionToAdvise exec result: ', result);\n    console.log('after functionToAdvise exec');\n});\n\n// log:\n// before functionToAdvise exec\n// functionToAdvise exec arguments: 1,2,3\n// functionToAdvise exec arguments: 1,2\n// functionToAdvise exec result: functionToAdvise return value\n// after functionToAdvise exec\nadvisedFunction(1, 2, 3);\n```\n\n### ProceedingJoinPoint\n\n```javascript\njoinPoint = {\n    // 函数被调用时的上下文\n    target: Object,\n\n    // 传给外层函数的参数\n    args: Array,\n\n    // 原方法名或函数名\n    method: string,\n\n    // 被调用时, 会调用被拦截的原函数, 并传入原始参数\n    proceed: Function,\n\n    // 被调用时, 会调用被拦截的原函数, 首个参数为被拦截函数要执行时的上下文, 第二个参数为要传递给被拦截函数的参数数组\n    proceedApply: Function\n}\n```\n\n#### createFunctionProxy(functionToAdvise, advices)\n\n创建一个组装了多个通知行为的函数代理, advices 为拥有 before, afterReturning, afterThrowing, after, around 中一个或多个方法的对象.\n\n### Object Method API\n\n提供针对对象方法的拦截。\n\n每个拦截接口都接收三个参数：被拦截对象，方法匹配规则 matcher，通知执行函数。\n\nmatcher 可为 string, RegExp, Function 的任意一种，为 Function 时，接收被拦截对象和当前方法名作为参数，执行结果返回 true 时，匹配成功，会对该方法执行拦截。\n\n每个拦截接口都会返回一个原对象的代理对象，代理对象会针对符合匹配规则的方法封装，根据通知类型，在方法执行的不同阶段，执行相关的通知逻辑。\n\n**注：原对象不受任何影响**\n\n#### before(objectToAdvise, matcher, beforeFunction)\n\n返回一个新的代理对象, 在 matcher 匹配的方法执行前，会执行 beforeFunction，beforeFunction 接收匹配方法执行时的参数\n\n**除非抛异常, 否则不会中断匹配方法的执行**\n\n```javascript\nvar toAdvise = {\n    method: function () {\n         console.log('method exec');\n    }\n};\n\nvar advisedObject = aop.before(toAdvise, 'method', function (arg) {\n      console.log('before method exec');\n      console.log(arg);\n});\n\n// log:\n// before method exec\n// a\n// method exec\nadvisedObject.method('a');\n\n// log:\n// method exec\ntoAdvise.method('a');\n```\n\n#### afterReturning(objectToAdvise, matcher, afterReturningFunction)\n\n返回一个新的代理对象, 在 matcher 匹配的方法正常执行后, 执行 afterReturningFunction,\nafterReturningFunction 接收匹配方法执行后的返回结果作为唯一参数, 不影响返回结果.\n\n```javascript\nvar toAdvise = {\n    method: function () {\n         console.log('method exec');\n         return 'toAdivse method result';\n    }\n};\n\nvar advisedObject = aop.afterReturning(toAdvise, 'method', function (returnValue) {\n    console.log('return value: ', returnValue);\n});\n\n// log:\n// method exec\n// return value: toAdivse method result\nadvisedObject.method();\n```\n\n#### afterThrowing(objectToAdvise, matcher, afterThrowingFunction)\n\n返回一个新的代理对象, 在 matcher 匹配的方法抛出异常后, 执行 afterThrowingFunction,\nafterThrowingFunction 接收匹配方法抛出的异常对象作为唯一参数.\n\n**通知不会吞噬原有异常, 会在 afterThrowingFunction 执行完毕后, 抛出原有异常**\n\n```javascript\nvar toAdvise = {\n    method: function (throwError) {\n         console.log('method exec');\n         if(throwError) {\n            throw new Error('method error');\n          }\n    }\n};\n\nvar advisedObject = aop.afterThrowing(toAdvise, 'method', function (e) {\n    console.log('execption: ', e.message);\n});\n\n// log:\n// method exec\nadvisedObject.method();\n\n// log:\n// method exec\n// execption: method error\nadvisedObject.method(true);\n```\n\n#### after(objectToAdvise, matcher, afterFunction)\n\n返回一个新的代理对象, 在 matcher 匹配的方法正常返回或抛出异常后, 执行 afterFunction。\n\n**通知不会吞噬原有异常, 会在 afterFunction 执行完毕后, 抛出原有异常**\n\n```javascript\nvar toAdvise = {\n    method: function (throwError) {\n        if(throwError) {\n           console.log('method exception');\n           throw new Error('error');\n        }\n\n        console.log('method exec');\n    }\n};\n\nvar advisedObject = aop.after(toAdvise, 'method', function () {\n    console.log('after method exec');\n});\n\n// log:\n// method exec\n// after method exec\nadvisedObject.method();\n\n// log:\n// method exception\n// after method exec\nadvisedObject.method(true);\n```\n\n#### around(objectToAdvise, matcher, aroundFunction)\n\n返回一个新的代理对象, 在 matcher 匹配的方法执行时, 执行 aroundFunction, aroundFunction 接收一个 ProceedingJoinPoint 对象作为参数,\n调用其 proceed/proceedApply 方法将执行原方法.\n\n```javascript\nvar toAdvise = {\n    method: function () {\n        console.log('method exec arguments: ', [].slice.call(arguments, 0));\n        return 'method return value';\n    }\n};\n\nvar advisedObject = aop.around(toAdvise, 'method', function (joinPoint) {\n    console.log('before method exec');\n    // proceed/proceedApply 可以多次调用, 会多次执行原方法, proceedApply 可以改变 this 和参数信息\n    var result = joinPoint.proceed();\n    result = joinPoint.proceedApply(null, [1, 2]);\n    console.log('method exec result: ', result);\n    console.log('after method exec');\n});\n\n// log:\n// before method exec\n// method exec arguments: 1,2,3\n// method exec arguments: 1,2\n// method exec result: method return value\n// after method exec\nadvisedObject.method(1, 2, 3);\n```\n\n#### createObjectProxy(objectToAdvise, matcher, advices)\n\n创建一个组装了通知行为的对象代理, 会重写符合匹配规则的方法, 织入通知逻辑.\n\nadvice 拥有 before, afterReturning, afterThrowing, after, around 中一个或多个方法的对象.\n\n### ProceedingJoinPoint\n\n同Function API 下的 ProceedingJoinPoint\n\n### Matcher\n\nmatcher 可以为以下三种类型:\n\n- string 匹配拦截对象中属性名与 matcher 相等的方法。\n- RegExp 匹配拦截对象中属性名符合 matcher 规则的方法。\n- Function 匹配拦截对象中属性名符合 matcher 执行结果的方法， matcher 接收拦截对象和当前属性名称作为参数，返回 true 则表示匹配成功。\n\n```javascript\nvar toAdvise = {\n    method: function () {},\n    foo: function () {},\n    foo1: function () {},\n    foo2: function () {},\n    init: function () {}\n};\n// 将拦截 toAdvise.method\nvar advisedObject = aop.before(toAdvise, 'method', function () {});\n\n// 将拦截 toAdvise.foo, toAdvise.foo1, toAdvise.foo2\nvar advisedObject = aop.before(toAdvise, /^foo/, function () {});\n\nvar fnMatcher = function (obj, name) {\n    return name !== 'init';\n};\n// 将拦截 toAdvise.foo, toAdvise.foo1, toAdvise.foo2, toAdvise.method\nvar advisedObject = aop.before(toAdvise, fnMatcher, function () {});\n```\n\n### Class Method API\n\n提供针对Class方法拦截的 API\n\n#### createClassProxy(Class, matcher, advices)\n\n创建一个组装了通知行为的类代理, 会重写符合匹配规则的方法, 织入通知逻辑.\n\nadvice 拥有 before, afterReturning, afterThrowing, after, around 中一个或多个方法的对象.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fecomfe%2Faop","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fecomfe%2Faop","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fecomfe%2Faop/lists"}