IOC之依赖注入原理

2021-09-10  本文已影响0人  做一只旅行青蛙

IOC的一个很重要的实现就是依赖注入,将用户对类实例化的操作权,反转给容器去做,由容器来处理类与类之间的依赖关系,从而可以降低模块与模块之间的耦合关系。

下面是手动实现的依赖注入原理:

// es7的提案,ts1.5+版本已经支持,可以通过他给类或者类的原型属性上添加元数据
import 'reflect-metadata';
 
const INJECTED = '__inject__';
 
type Constructor<T = any> = new (...args: any[]) => T;
 
// 定义一个装饰器,他可以在类的构造函数上定义元数据,定义的元数据是构造函数的所有参数
const Injectable = (): ClassDecorator => (constructor) => {
  Reflect.defineMetadata(
    INJECTED,
    Reflect.getMetadata('design:paramtypes', constructor), // 这里还支持两外两种内置元数据定义,一个是design:type获取属性类型,一个是design:returntype获取返回值类型
    constructor,
  );
};
 
@Injectable()
class AService {
  a = 1;
}
 
@Injectable()
class BService {
  b = 2;
  constructor(private aService: AService) {}
}
 
@Injectable()
class TestService {
  constructor(
    private obj,
    private aService: AService,
    private bService: BService,
  ) {}
}
 
const getInstance = <T>(target: Constructor<T>): T => {
  // 获取所有注入的服务
  const providers = Reflect.getMetadata(INJECTED, target);
  const args =
    providers?.map((provider: Constructor) => {
      console.log(provider);
      return getInstance(provider); // 递归实例化所有依赖
    }) ?? [];
  return new target(...args);
};
 
console.log(getInstance(TestService));
 
// 打印结果:
/*
 *  [Function: Object]
 *  [class AService]
 *  [class BService]
 *  [class AService]
 *  TestService {
 *      obj: {},
 *      aService: AService { a: 1 },
 *      bService: BService { aService: AService { a: 1 }, b: 2 }
 *  }
*/

特点:通过容器完成对象的装配,注入到需要的对象(被动获取)
因此依赖注入又被称之为好莱坞原则:”Don't call us, we'll call you”,有事儿不要找我们,如果有需要我们会找你!

上一篇下一篇

猜你喜欢

热点阅读