AOP是什么
Spring中AOP是面向切面编程。EggBornJS同样也实现了AOP机制,可以对Bean组件进行逻辑扩展
定义AOP
由于AOP也是一种Bean,因此也有两种定义模式:app和ctx。下面以ctx模式为例
src/suite-vendor/test-party/modules/test-party/backend/src/aop/regExp.js
module.exports = ctx => {
class regExpAop {
get__name(context, next) {
next();
context.value = `${context.value}:regexpaop`;
}
set__name(context, next) {
const parts = context.value.split(':');
const index = parts.indexOf('regexpaop');
if (index > -1) {
parts.splice(index, 1);
}
context.value = parts.join(':');
next();
}
actionSync(context, next) {
next();
context.result = `${context.result}:regexpaop`;
}
async actionAsync(context, next) {
await next();
context.result = `${context.result}:regexpaop`;
}
}
return regExpAop;
};
1. 属性AOP
在对Bean属性进行AOP时,需要创建两个方法,使用约定的前缀: get__
和set__
名称 | 说明 |
---|---|
context | Bean属性的环境参数 |
next | 由于Bean组件可以挂载多个AOP,形成AOP调用链 ,因此需要调用next 让调用链可以继续,类似于KOA的洋葱圈模型 |
- context
名称 | 说明 |
---|---|
target | Bean实例 |
receiver | Bean的Proxy实例 |
prop | Bean实例的属性名 |
method | AOP当前被调用的方法名 |
value | 属性值 |
2. 方法AOP
在对Bean方法进行AOP时,方法名保持不变,但是需要采用约定的传参格式
名称 | 说明 |
---|---|
context | Bean方法的环境参数 |
next | 由于Bean组件可以挂载多个AOP,形成AOP调用链 ,因此需要调用next 让调用链可以继续,类似于KOA的洋葱圈模型 |
- context
名称 | 说明 |
---|---|
target | Bean实例 |
receiver | Bean的Proxy实例 |
prop | Bean实例的方法名 |
arguments | Bean方法的实际传参 |
result | Bean方法的计算结果,最终作为返回值 |
洋葱圈模型
与5种AOP通知类型
Spring的AOP有5种通知类型,分别是:@Before、@After、@AfterReturning、@AfterThrowing、@Around
而EggBornJS中的AOP采用洋葱圈模型
,只需一种方式即可同时支持Spring的5种AOP通知类型
注册AOP
AOP的注册方式与Bean类似
src/suite-vendor/test-party/modules/test-party/backend/src/aops.js
const regExp = require('./aop/regExp.js');
const simple = require('./aop/simple.js');
module.exports = app => {
const aops = {};
if (app.meta.isTest || app.meta.isLocal) {
Object.assign(aops, {
simple: {
match: 'testctx',
mode: 'ctx',
bean: simple,
},
regExp: {
match: [ /^test-party.test\.\w+$/, 'testctx' ],
mode: 'ctx',
bean: regExp,
},
});
}
return aops;
};
名称 | 说明 |
---|---|
mode | 模式:app/ctx |
bean | aop组件(也是一种Bean组件) |
match | 匹配beanFullName |
- match可以设置如下类型
- String: 精确匹配beanFullName
- RegExp: 按RegExp对beanFullName进行匹配测试
- Array[String/RegExp]: 任何一个匹配通过即可
评论: