欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

typescript nodejs 依賴注入實(shí)現(xiàn)方法代碼詳解

 更新時(shí)間:2019年07月21日 08:59:09   作者:村長(zhǎng)lv  
今天分享的是用typescript語(yǔ)言實(shí)現(xiàn)的ioc模式,這邊用到的主要組件是 reflect-metadata 這個(gè)組件可以獲取或者設(shè)置元數(shù)據(jù)信息,接下來(lái)通過(guò)本文給大家介紹typescript nodejs 依賴注入實(shí)現(xiàn)方法,需要的朋友可以參考下

依賴注入通常也是我們所說(shuō)的ioc模式,今天分享的是用typescript語(yǔ)言實(shí)現(xiàn)的ioc模式,這邊用到的主要組件是 reflect-metadata 這個(gè)組件可以獲取或者設(shè)置元數(shù)據(jù)信息,它的作用是拿到原數(shù)據(jù)后進(jìn)行對(duì)象創(chuàng)建類似C#中的反射,先看第一段代碼:

import "reflect-metadata";
/**
 * 對(duì)象管理器
 */
const _partialContainer = new Map<string, any>();
const PARAMTYPES = "design:paramtypes";//需要反射的原數(shù)據(jù),有很多種選擇,我們這里選擇的是拿到構(gòu)造函數(shù)的參數(shù)類型,為了后續(xù)判斷
/**
 * 局部注入器,注入的是全局服務(wù),實(shí)例是全局共享
 */
export function Inject(): ClassDecorator {
  return target => {
    const params: Array<any> = Reflect.getMetadata(PARAMTYPES, target);
    if (params)
      for (const item of params) {
        if (item === target) throw new Error("不能注入自己");
      }
    _partialContainer.set(target.name, target);//加入到對(duì)象管理器中,這個(gè)時(shí)候?qū)ο筮€沒(méi)有被創(chuàng)建
  }
}

   上面的代碼是創(chuàng)建一個(gè)類級(jí)別的裝飾器,表示凡是使用了這個(gè)裝飾器的類都會(huì)被依賴注入對(duì)象管理器管理,這里沒(méi)有馬上創(chuàng)建服務(wù),原因是reflect-metadata的執(zhí)行有先機(jī)是最高的,而這個(gè)依賴注入是支持手動(dòng)注入一些實(shí)例對(duì)象,所有為了防止出現(xiàn)注入?yún)?shù)為undefined所以創(chuàng)建實(shí)例的工作是放在后面的,請(qǐng)看接下來(lái)的代碼:

/**
 *
 * @param type 已創(chuàng)建的實(shí)例對(duì)象
 */
export function addServiceInGlobal(...types: Array<Object>) {
  for (const iterator of types) {
    _partialContainer.set(iterator.constructor.name, iterator);
  }
}

 上面的方法是手動(dòng)注入實(shí)例對(duì)象時(shí)調(diào)用的,我們需要提高這個(gè)方法的執(zhí)行優(yōu)先級(jí),具體的實(shí)例會(huì)在后面演示,接下來(lái)是最重要部分,創(chuàng)建實(shí)例部分:

export function serviceProvider<T>(service: ServiceType<T>): T {
  if (_partialContainer.has(service.name) && !_partialContainer.get(service.name).name)
    return _partialContainer.get(service.name);// 如果實(shí)例已經(jīng)被創(chuàng)建就直接返回
 
  const params: Array<any> = Reflect.getMetadata(PARAMTYPES, service);// 反射拿到構(gòu)造函數(shù)的參數(shù)類型
  const constrparams = params.map(item => { // 實(shí)例化參數(shù)中的依賴
    if (!_partialContainer.has(item.name)) throw new Error(`${item}沒(méi)有被注入`);// 如果沒(méi)有注入就拋出異常
    if (item.length)// 表示這個(gè)類型還有其它依賴
      return serviceProvider(item);// 遞歸繼續(xù)獲取其他依賴
    if (_partialContainer.has(item.name) && !_partialContainer.get(item.name).name)
      return _partialContainer.get(item.name);// 如果實(shí)例已經(jīng)被創(chuàng)建就直接返回
    const obj = new item();// 已經(jīng)沒(méi)有其他依賴了 開(kāi)始創(chuàng)建實(shí)例
    _partialContainer.set(item.name, obj);// 替換對(duì)象管理器中原來(lái)沒(méi)有實(shí)例化的對(duì)象
    return obj;
  });
  const obj = new service(...constrparams); // 這里表示對(duì)象沒(méi)有被創(chuàng)建,開(kāi)始創(chuàng)建對(duì)象
  _partialContainer.set(service.name, obj);// 替換對(duì)象管理器中原來(lái)沒(méi)有實(shí)例化的對(duì)象
  return obj;
}

 上面代碼寫的稍微有一點(diǎn)點(diǎn)復(fù)雜,其他理解起來(lái)也不困難,大白話講就是 如果已經(jīng)實(shí)例化了直接返回實(shí)例不然就開(kāi)始對(duì)象以及創(chuàng)建出所有的依賴。接下來(lái)是例子:

import { serviceProvider, addServiceInGlobal, Inject } from './core/injectable/injector';
import "reflect-metadata";
import moment = require('moment');
@Inject()
export class ServiceA{
  property?:string;
  msg(){
    return "ServiceA";
  }
}
@Inject()
export class ServiceC {
  constructor(private service: ServiceA) { }
  print() {
   console.log( this.service.property);
    return "調(diào)用了我";
  }
}
@Inject()
export class ServiceD{
  print(){
   console.log("我在測(cè)試注入");
  }
}
@Inject()
export class GlobalService {
  constructor(private service: ServiceC) { }
  msg!: string;
  print() {
    console.log(`共享模塊${this.service.print()}`)
  }
}
@Inject()
export class Init {
  constructor(private service: ServiceA,
    private serviceD: ServiceD,
    private global: GlobalService,
    private date: Date,
    private strList: string[],
    private serviceC: ServiceC,
  ) { }
  start() {
    console.log(this.service.msg());
    this.service.property = "A模塊設(shè)置的共享數(shù)據(jù)"
    console.log(moment(this.date).format("YYYY-MM-DD"))
    console.log(this.strList);
    this.serviceD.print();
    this.serviceC.print();
    this.global.print();
  }
}
 
const obj = new Date("2017-1-1");
const str = ['呂順彬','菜鳥(niǎo)','豆豆','大鐵','CC哥','碼農(nóng)之家的一群人'];
addServiceInGlobal(obj, str); // 添加手動(dòng)創(chuàng)建的實(shí)例對(duì)象到對(duì)象管理器
const service = serviceProvider(Init); // 開(kāi)始創(chuàng)建實(shí)例
service.start()// 執(zhí)行

上面的實(shí)例中得到一下執(zhí)行結(jié)果:

總結(jié):上面我用的是默認(rèn)全局注入,沒(méi)有做singletion (單例) ,如果要做的話稍微修改下代碼就可以實(shí)現(xiàn),這里邊的難點(diǎn)可能是基于反射的設(shè)計(jì)方法,如果前端思維可能理解起來(lái)稍微困難點(diǎn),后臺(tái)的話稍微好點(diǎn)。

總結(jié)

以上所述是小編給大家介紹的typescript nodejs 依賴注入實(shí)現(xiàn)方法代碼詳解,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)歡迎給我留言,小編會(huì)及時(shí)回復(fù)大家的!

相關(guān)文章

  • Ubuntu中搭建Nodejs開(kāi)發(fā)環(huán)境過(guò)程分享

    Ubuntu中搭建Nodejs開(kāi)發(fā)環(huán)境過(guò)程分享

    這篇文章主要介紹了Ubuntu中搭建Nodejs開(kāi)發(fā)環(huán)境過(guò)程,比較郁悶的是apt-get安裝失敗了,如果有遇到一樣問(wèn)題的朋友,可以參考一下本文
    2014-06-06
  • Nodejs爬蟲(chóng)進(jìn)階教程之異步并發(fā)控制

    Nodejs爬蟲(chóng)進(jìn)階教程之異步并發(fā)控制

    這篇文章主要介紹了Nodejs爬蟲(chóng)進(jìn)階教程之異步并發(fā)控制的相關(guān)資料,需要的朋友可以參考下
    2016-02-02
  • Nodejs異步回調(diào)之異常處理實(shí)例分析

    Nodejs異步回調(diào)之異常處理實(shí)例分析

    這篇文章主要介紹了Nodejs異步回調(diào)之異常處理,結(jié)合實(shí)例形式分析了nodejs基于中間件進(jìn)行異步回調(diào)異常處理過(guò)程出現(xiàn)的問(wèn)題與相應(yīng)的解決方法,需要的朋友可以參考下
    2018-06-06
  • pnpm的安裝及其使用教程(匯總)

    pnpm的安裝及其使用教程(匯總)

    pnpm是 Node.js 的替代包管理器,它是 npm 的直接替代品,速度更快、效率更高,它由 npm/yarn 衍生而來(lái),但卻解決了 npm/yarn 內(nèi)部潛在的 bug,并且極大了地優(yōu)化了性能,本文給大家介紹pnpm的安裝及其使用,感興趣的朋友一起看看吧
    2023-12-12
  • Node.js JSON模塊用法實(shí)例分析

    Node.js JSON模塊用法實(shí)例分析

    這篇文章主要介紹了Node.js JSON模塊用法,結(jié)合實(shí)例形式分析了node.js json模塊的基本語(yǔ)法,以及使用json模塊進(jìn)行json格式數(shù)據(jù)解析的相關(guān)操作技巧,需要的朋友可以參考下
    2019-01-01
  • 參考EventEmitter實(shí)現(xiàn)完整訂閱發(fā)布功能函數(shù)

    參考EventEmitter實(shí)現(xiàn)完整訂閱發(fā)布功能函數(shù)

    這篇文章主要為大家介紹了參考EventEmitter實(shí)現(xiàn)完整訂閱發(fā)布功能函數(shù)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • 解決node.js安裝包失敗的幾種方法

    解決node.js安裝包失敗的幾種方法

    nodejs安裝包失敗的原因可能有很多,下面這篇文章給大家整理三種方法來(lái)解決,大家可以試一試或許可以解決你的問(wèn)題,下面來(lái)一起看一看。
    2016-09-09
  • Node.js使用SQLite數(shù)據(jù)庫(kù)方法大全

    Node.js使用SQLite數(shù)據(jù)庫(kù)方法大全

    Node.js是一種流行的JavaScript運(yùn)行時(shí),提供了許多有用的模塊和庫(kù)來(lái)構(gòu)建Web應(yīng)用程序,而SQLite是一種嵌入式關(guān)系型數(shù)據(jù)庫(kù),它可以運(yùn)行在各種操作系統(tǒng)上,包括Windows、Linux和Mac OS X等,在Node.js中,可以通過(guò)安裝sqlite3模塊來(lái)訪問(wèn)SQLite數(shù)據(jù)庫(kù)
    2023-10-10
  • 學(xué)習(xí) NodeJS 第八天:Socket 通訊實(shí)例

    學(xué)習(xí) NodeJS 第八天:Socket 通訊實(shí)例

    本篇文章主要介紹了學(xué)習(xí) NodeJS 第八天:Socket 通訊實(shí)例,非常具有實(shí)用價(jià)值,需要的朋友可以參考下。
    2016-12-12
  • node事件循環(huán)和process模塊實(shí)例分析

    node事件循環(huán)和process模塊實(shí)例分析

    這篇文章主要介紹了node事件循環(huán)和process模塊,結(jié)合實(shí)例形式分析了node事件循環(huán)和process模塊具體功能、使用方法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下
    2020-02-02

最新評(píng)論