介绍

我们知道Bean容器IOC控制反转是进行系统解耦行之有效的架构设计。实现IOC控制反转主要有两种策略:

  1. 依赖注入:比如Java Spring、Node NestJS

  2. 依赖查找:EggBorn则是在原生JS(Vanilla JS)上实现了更轻量、更灵活的Bean容器,并采取了依赖查找的使用策略

理念

EggBorn在设计Bean容器机制时,遵循了以下3个理念:

1. 几乎所有事物都是Bean

我们绝大多数逻辑代码都通过Bean组件进行管理。比如:Controller、Service、Model、Middleware、Event、Queue、Broadcast、Schedule、Startup、Flow、Flow Task,等等

2. Bean支持AOP

所有Bean组件都可以通过AOP组件进行逻辑扩展

3. AOP也是一种Bean

AOP组件既然也是Bean,那么也可以通过其他AOP组件进行逻辑扩展

这种递归设计,为系统的可定制性和延展性,提供了强大的想象空间

定义Bean组件

EggBornJS约定了两种定义Bean组件的模式:appctx。二者的主要区别就是当Bean组件被实例化时的传参不同

由于Bean组件Bean容器托管,可以很方便的跨模块调用。因此,为了清晰的辨识Bean组件被调用的场景,一般约定:如果Bean组件只被本模块内部调用,那么就使用app模式;如果大概率会被跨模块调用,那么就使用ctx模式

1. app模式

比如:Controller、Service都采用app模式

src/suite-vendor/test-party/modules/test-party/backend/src/bean/test.app.js

  1. 1module.exports = app => {
  2. 2
  3. 3 class appBean extends app.meta.BeanBase {
  4. 4
  5. 5 actionSync({ a, b }) {
  6. 6 return a + b;
  7. 7 }
  8. 8
  9. 9 async actionAsync({ a, b }) {
  10. 10 return Promise.resolve(a + b);
  11. 11 }
  12. 12
  13. 13 }
  14. 14
  15. 15 return appBean;
  16. 16};

2. ctx模式

比如:ctx.bean.atomctx.bean.userctx.bean.role都采用ctx模式

src/suite-vendor/test-party/modules/test-party/backend/src/bean/test.ctx.js

  1. 1module.exports = ctx => {
  2. 2 class ctxBean {
  3. 3
  4. 4 constructor(moduleName) {
  5. 5 this._name = moduleName || ctx.module.info.relativeName;
  6. 6 }
  7. 7
  8. 8 get name() {
  9. 9 return this._name;
  10. 10 }
  11. 11
  12. 12 set name(value) {
  13. 13 this._name = value;
  14. 14 }
  15. 15
  16. 16 actionSync({ a, b }) {
  17. 17 return a + b;
  18. 18 }
  19. 19
  20. 20 async actionAsync({ a, b }) {
  21. 21 return Promise.resolve(a + b);
  22. 22 }
  23. 23
  24. 24 }
  25. 25
  26. 26 return ctxBean;
  27. 27};

ctx.module.info.relativeName: 由于ctx模式的Bean经常被其他模块调用,那么可以通过此属性取得调用方模块的名称

注册Bean

对于大多数组件,EggJS采用约定优先的策略,会在指定的位置查找资源,并自动加载。而EggBornJS需要显式注册,从而Webpack可以收集所有后端源码,实现模块编译的特性

src/suite-vendor/test-party/modules/test-party/backend/src/beans.js

  1. 1const testApp = require('./bean/test.app.js');
  2. 2const testCtx = require('./bean/test.ctx.js');
  3. 3
  4. 4module.exports = app => {
  5. 5 const beans = {
  6. 6 // test
  7. 7 'test.app': {
  8. 8 mode: 'app',
  9. 9 bean: testApp,
  10. 10 },
  11. 11 testctx: {
  12. 12 mode: 'ctx',
  13. 13 bean: testCtx,
  14. 14 global: true,
  15. 15 },
  16. 16 };
  17. 17 return beans;
  18. 18};
名称 说明
mode 模式:app/ctx
bean bean组件
global 是否是全局组件