框架增强注入

midway 默认使用 injection 这个包来做依赖注入,虽然 @inject 装饰器能满足大多数业务的需求,但是对于框架来说,还有需要需要扩展和使用的地方,比如插件,配置等等。

注入插件

midway 除了支持 eggjs 原本的 app.xx 的插件用法,同时,也可以通过 @plugin 装饰器来注入插件。

比如我们提供了一个名字叫 plugin2 的插件,就可以通过属性注入的方式来修饰插件。

注意

由于在 midway 内部插件未放在 applicationContext 中,所以不能使用 @inject 来注入

  1. @provide()
  2. export class BaseService {
  3. @plugin('plugin2')
  4. plugin;
  5. }

这个时候我们就需要拿到插件的名字。

TIP

插件,在 midway 中为单例,不可配置。

查找插件名

这个插件的名字和普通的插件名字,他是根据插件代码中的返回而定的。

midway 会将挂载到 app 上的属性名作为基础 key。

  1. module.exports = (app) => {
  2. // egg 插件经常这么做
  3. app.plugin1 = xxxx;
  4. }

那么 plugin1 就是插件key,midway 会在给 app 赋值时自动将返回的对象挂载到插件上下文中,供 @plugin 装饰器调用。

注入配置

在 midway 中不同环境的 config 都会挂载到 app.config 中,但是不是所有的业务逻辑都会依赖 app 对象,所以我们构造了 @config 装饰器来获取配置对象。

假如 config.default.ts 中有一些代码。

  1. export const hello = 1;
  1. @provide()
  2. export class BaseService {
  3. @config('hello')
  4. config; // 1
  5. }

通过这样,我们可以把 config 中的值直接注入到业务逻辑中。

注册定时任务

midawy 的定时任务是基于 egg 定时任务提供了更多 typescript 以及装饰器方面的支持。将定时任务都统一存放在 lib/schedule 目录下,每一个文件都是一个独立的定时任务,可以配置定时任务的属性和要执行的方法。例如:

  1. // src/lib/schedule/hello.ts
  2. 'use strict';
  3. import { schedule } from 'midway';
  4. @schedule({
  5. interval: 2333, // 2.333s 间隔
  6. type: 'worker', // 指定某一个 worker 执行
  7. })
  8. export class HelloCron {
  9. // 定时执行的具体任务
  10. async exec(ctx) {
  11. ctx.logger.info(process.pid, 'hello');
  12. }
  13. }

PS: 定时任务类需 export 导出才会被加载,并且一个 .ts 文件可以 export 多个定时任务类,但是如果 export default 了,则只会读取 default 的类。

注入日志对象

在原有逻辑中,日志对象也都挂载在 app.loggers 中,通过在 config 中配置的 key 来生成不同的日志实例对象,比如插件的日志,链路的日志等。

比如自定义一个日志,这个时候,日志的 key 则为 customLogger

  1. module.exports = appInfo => {
  2. return {
  3. customLogger: {
  4. xxLogger: {
  5. file: path.join(appInfo.root, 'logs/xx.log'),
  6. },
  7. },
  8. };
  9. };

这个时候可以用 @logger 来获取日志实例。

  1. @provide()
  2. export class BaseService {
  3. @logger('customLogger')
  4. logger;
  5. }

请求作用域中的日志

midway 在新版本中默认对所有对象开启了请求作用域,处于该作用域下的对象,都会包含一个默认的日志对象。

TIP

该 logger 对象是在请求链路开始就埋入到 IoC 容器中,所以可以通过 @inject 可以获取该对象, key 就为 logger,如果和属性同名则可以不填。

  1. @provide()
  2. export class BaseService {
  3. @inject()
  4. logger;
  5. // 也可以直接传入 key
  6. // @inject('logger')
  7. // logger;
  8. }