AOP 中间件
使用场景
一个请求进来后,会执行一系列处理,然后返回响应给用户。这个过程像一条管道,管道的每一个切面逻辑,称为 Middleware
。这种模型也被形象地称为“洋葱模型”。
Middleware
非常适合用于实现如日志记录、安全校验等与具体业务无关的横切面逻辑。
开启插件
typescript
// config/plugin.ts
export default {
aopModule: true,
};
标准 AOP 写法
标准 AOP 实现方式满足绝大部份场景,完全按照 AOP 装饰器使用方式实现即可。
typescript
import { Inject, Logger, ObjectInitType, Tracer } from 'egg';
import { Advice, IAdvice, AdviceContext } from 'egg/aop';
@Advice({ initType: ObjectInitType.SINGLETON })
export class SimpleAopAdvice implements IAdvice {
@Inject()
logger: Logger;
@Inject()
tracer: Tracer;
async around(ctx: AdviceContext, next: () => Promise<any>) {
// 控制器前执行的逻辑
const startTime = Date.now();
this.logger.info('args: %j', ctx.args); // 调用 controller 方法,传入的参数
// 执行下一个 middleware
const res = await next();
// 控制器之后执行的逻辑
this.logger.info(
'%dms, traceId: %s',
Date.now() - startTime,
this.tracer.traceId,
);
// 对结果进行处理后,再返回
return {
res,
traceId: this.tracer.traceId,
};
}
}
使用 Middleware
实现好中间件逻辑后,通过 Middleware
装饰器,将中间件应用于具体的 controller 中,使其生效。Middleware
装饰器可用于 controller 类或者 controller 类中的方法。
Middleware
装饰器用于类上时,表示该类的所有方法都会应用该中间件。Middleware
装饰器用于方法上时,表示只有该方法会应用该中间件。- 若类和方法上都有
Middleware
装饰器,会先执行类上的中间件,再执行方法上的中间件。 - 若混用 Aop 中间件和函数式中间件,函数式中间件会先于所有 Aop 中间件执行。
typescript
import { Middleware } from 'egg';
@Middleware(globalLog)
export class FooController {
// 执行顺序
// 进
// 1. globalLog(ctx, next)
// 2. methodCount(ctx, next)
// 3. hello()
// 出
// 4. methodCount(ctx, next)
// 5. globalLog(ctx, next)
@Middleware(methodCount)
async hello() {}
// 执行顺序
// 进
// 1. globalLog(ctx, next)
// 2. methodCount3(ctx, next)
// 3. methodCount2(ctx, next)
// 4. methodCount1(ctx, next)
// 5. mulitple()
// 出
// 6. methodCount1(ctx, next)
// 7. methodCount2(ctx, next)
// 8. methodCount3(ctx, next)
// 9. globalLog(ctx, next)
@Middleware(methodCount1)
@Middleware(methodCount2)
@Middleware(methodCount3)
async multiple() {}
// 执行顺序
// 进
// 1. globalLog(ctx, next)
// 2. bye()
// 出
// 3. globalLog(ctx, next)
async bye() {}
}