ng-book札记——依赖注入

来源:http://www.prospettivedarte.com 作者:计算机教程 人气:112 发布时间:2019-05-10
摘要:依赖注入是一种使程序的一部分能够访问另一部分的系统,并且可以通过配置控制其行为。   “注入”可以理解为是“new”操作符的一种替代,不再需要使用编程语言所提供的"new"操作

依赖注入是一种使程序的一部分能够访问另一部分的系统,并且可以通过配置控制其行为。

 

“注入”可以理解为是“new”操作符的一种替代,不再需要使用编程语言所提供的"new"操作符,依赖注入系统管理对象的生成。

皇牌天下投注网 1

依赖注入的最大好处是组件不再需要知道如何建立依赖项。它们只需要知道如何与依赖项交互。

 

在Angular的依赖注入系统中,不用直接导入并创建类的实例,而是使用Angular注册依赖,然后描述如何注入依赖,最后注入依赖。

 

依赖注入组件

为了注册一个依赖项,需要使用依赖标记(token)与之绑定。比如,注册一个API的URL,可以使用字符串API_URL作为其标记;如果是注册一个类,可以用类本身作为标记。

Angular中的依赖注入系统分为三部分:

  • 皇牌天下投注网,提供者(Provider)(也被作为一个绑定)映射一个标记到一系列的依赖项,其告知Angular如何创建一个对象并给予一个标记。
  • 注入器(Injector)持有一系列绑定,并负责解析依赖项,且在创建对象的时候注入它们。
  • 依赖项(Dependency)是所注入的对象。

皇牌天下投注网 2

一、依赖注入

依赖注入方式

a) 如果模块A需要依赖模块B,通常的做法是在A中导入B,import{B} from ‘B’,但有一些场合需要解除这种直接依赖,比如单元测试时需要mock一个B对象、还有时要创建B的单例或者用工厂模式生成B,这时适合使用依赖注入(Dependency Injection)的方式来解除对B的直接依赖。

手动方式

通过ReflectiveInjectorresolveAndCreate方法解析并创建对象,这种方式不常用。

import { Injectable } from '@angular/core';

@Injectable()
export class UserService {
  user: any;

  setUser(newUser) {
    this.user = newUser;
  }

  getUser(): any {
    return this.user;
  }
}

import {
  Component,
  ReflectiveInjector
} from '@angular/core';

import { UserService } from '../services/user.service';

@Component({
  selector: 'app-injector-demo',
  templateUrl: './user-demo.component.html',
  styleUrls: ['./user-demo.component.css']
})
export class UserDemoInjectorComponent {
  userName: string;
  userService: UserService;

  constructor() {
    // Create an _injector_ and ask for it to resolve and create a UserService
    const injector: any = ReflectiveInjector.resolveAndCreate([UserService]);

    // use the injector to **get the instance** of the UserService
    this.userService = injector.get(UserService);
  }

  signIn(): void {
    // when we sign in, set the user
    // this mimics filling out a login form
    this.userService.setUser({
      name: 'Nate Murray'
    });

    // now **read** the user name from the service
    this.userName = this.userService.getUser().name;
    console.log('User name is: ', this.userName);
  }
}

* 注意UserService类上的@Injectable()装饰器,这说明了这个类是可以作为注入对象的。

 

NgModule方式

使用NgModule注册将要用到的依赖项(在providers中),并用装饰器(一般是构造器)指定哪些是正在使用的。

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';

// imported here
import { UserService } from '../services/user.service';

@NgModule({
  imports: [
    CommonModule
  ],
  providers: [
    UserService // <-- added right here
  ],
  declarations: []
})
export class UserDemoModule { }

import { Component, OnInit } from '@angular/core';

import { UserService } from '../services/user.service';

@Component({
  selector: 'app-user-demo',
  templateUrl: './user-demo.component.html',
  styleUrls: ['./user-demo.component.css']
})
export class UserDemoComponent {
  userName: string;
  // removed `userService` because of constructor shorthand below

  // Angular will inject the singleton instance of `UserService` here.
  // We set it as a property with `private`.
  constructor(private userService: UserService) {
    // empty because we don't have to do anything else!
  }

  // below is the same...
  signIn(): void {
    // when we sign in, set the user
    // this mimics filling out a login form
    this.userService.setUser({
      name: 'Nate Murray'
    });

    // now **read** the user name from the service
    this.userName = this.userService.getUser().name;
    console.log('User name is: ', this.userName);
  }
}

b) Angular的依赖注入框架包含三部分,Provider、Injector、Dependency,三者的关系为:

Providers

皇牌天下投注网 3

类标记

providers: [ UserService ]是以下方式的的简写:

providers: [
  { provide: UserService, useClass: UserService }
]

provide是标记,useClass是所依赖的对象。两者为映射关系。

Provider的作用是建立类与其依赖项之间的映射(mapbinding);Dependency为依赖项;Injector负责在创建对象的时候解析相关的依赖并根据Provider提供的绑定信息进行注入。

值标记

providers: [
  { provide: 'API_URL', useValue: 'http://my.api.com/v1' }
]

使用时需要加上@Inject:

import { Inject } from '@angular/core';

export class AnalyticsDemoComponent {
  constructor(@Inject('API_URL') apiUrl: string) {
    // works! do something w/ apiUrl
  }
}

 

工厂方式

绑定依赖项时还可以通过工厂方式实现更复杂的绑定逻辑,并且这种方式下可以传入必要参数以创建所需的对象。

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import {
  Metric,
  AnalyticsImplementation
} from './analytics-demo.interface';
import { AnalyticsService } from '../services/analytics.service';

// added this ->
import {
  HttpModule,
  Http
} from '@angular/http';

@NgModule({
  imports: [
    CommonModule,
    HttpModule, // <-- added
  ],
  providers: [
    // add our API_URL provider
    { provide: 'API_URL', useValue: 'http://devserver.com' },
    {
      provide: AnalyticsService,

      // add our `deps` to specify the factory depencies
      deps: [ Http, 'API_URL' ],

      // notice we've added arguments here
      // the order matches the deps order
      useFactory(http: Http, apiUrl: string) {

        // create an implementation that will log the event
        const loggingImplementation: AnalyticsImplementation = {
          recordEvent: (metric: Metric): void => {
            console.log('The metric is:', metric);
            console.log('Sending to: ', apiUrl);
            // ... You'd send the metric using http here ...
          }
        };

        // create our new `AnalyticsService` with the implementation
        return new AnalyticsService(loggingImplementation);
      }
    },
  ],
  declarations: [ ]
})
export class AnalyticsDemoModule { }

c) 记录用户登录信息的UserService是一个全局单例,对其注入并使用的例子为:

style="font-family: 微软雅黑, sans-serif; font-size: 16px">import{ Component, ReflectiveInjector } from '@angular/core';

style="font-family: 微软雅黑, sans-serif; font-size: 16px">import{ UserService } from '../services/user.service';

style="font-family: 微软雅黑, sans-serif; font-size: 16px">…

style="font-family: 微软雅黑, sans-serif; font-size: 16px">exportclass UserDemoComponent {

  userName: string;

  userService: UserService;

  constructor() {

    const injector: any =

style="font-family: 微软雅黑, sans-serif; font-size: 16px">ReflectiveInjector.resolveAndCreate([UserService]);

    this.userService =injector.get(UserService);

  }

  signIn(): void {

    this.userService.setUser({ name: 'Dante'});

    this.userName =this.userService.getUser().name;

  }

style="font-family: 微软雅黑, sans-serif; font-size: 16px">}

导入ReflectiveInjector类后,使用它的静态方法resolveAndCreate来创建一个injector,可被注入的内容以数组的形式从参数传入,injector.get(UserService)可以解析出一个UserService对象,这里将类本身作为token。

 

二、使用NgModule进行注入

a) 通过前面的代码可以直观地了解注入的过程,但实际使用中却不这样做,而是要在NgModule的providers中注册依赖项,然后通过装饰器在需要使用的类的构造函数中注入:

style="font-family: 微软雅黑, sans-serif; font-size: 16px">constructor(privateuserService: UserService) {}

需要注意的是,被注入的类要用@Injectable标记,而且这样是以单例的方式注入的,还有其它注入的形式,比如非单例类、注入一个值、调用方法并把方法的返回值注入等。

本文由皇牌天下投注网发布于计算机教程,转载请注明出处:ng-book札记——依赖注入

关键词:

上一篇:关于parseInt的看法

下一篇:没有了

最火资讯