nestjs中面向切面编程分为以下几个部分:中间件、Guard、Interceptor、Pipe、Filter
一、按照使用方式来分类:
1中间件:在模块的configure方法中进行配置,其配置是以代码形式进行的,当所有模块扫描完、组件创建之后,在NestApplication的setupModules方法中进行设置
2Guard、Interceptor、Pipe、Filter:使用装饰器在路由类、路由方法、路由方法参数上设置
二、按照实例获取方式来分类
1中间件:由于中间件类只出现在configure方法中,所以在之前扫描模块时并不知道这个类,只有当设置中间件时才会获取其实例,使用方法为:
@nestjs/core/injector/injector.ts
//加载中间件实例
public async loadInstanceOfMiddleware(
wrapper: MiddlewareWrapper,
collection: Map<string, MiddlewareWrapper>,
module: Module) {
//中间件类型
const { metatype } = wrapper;
//中间件包装器
const currentMetatype = collection.get(metatype.name);
//如果包装器中已经有实例,直接返回
if (currentMetatype.instance !== null) return;
//如果实例不存在,解析构造函数参数,最后使用参数实例创建中间件实例,说明中间件也可以依赖注入
await this.resolveConstructorParams(wrapper as any, module, null, null, (instances) => {
collection.set(metatype.name, {
instance: new metatype(...instances),
metatype,
});
});
}
可以看到,中间件对象也是使用注射器生成,说明它可以被注入组件,但是这一步与其他注入实例生成的时机是不一样的
2.Guard、Interceptor:UseGuards、UseInterceptors装饰器分别设置了他们的类,在扫描模块时扫描到这些元数据,并生成其实例,说明他们也是可以被注入组件的
@nestjs/core/injector/injector.ts
//加载可注入类实例
public async loadInstanceOfInjectable(wrapper: InstanceWrapper<Controller>, module: Module) {
//获取可注入类Map
const injectables = module.injectables;
//加载实例
await this.loadInstance<Controller>(wrapper, injectables, module);
}
3.Filter、Pipe:UseFilters、UsePipes装饰器直接设置它们的实例,所以不能进行组件注入
三、按照切面位置来区分
所有的切面都是围绕着express来处理的
1.中间件:直接设置为express中间件,在其相应路由之前执行
2.Guard、Interceptor、Pipe:在创建路由方法上下文时,加入相应的执行方法
3.Filter:当路由执行方法抛出异常时,由过滤器处理