详解Angular依赖注入

目录
  • 概述
  • 一、依赖注入
  • 二、Angular的依赖注入框架

概述

依赖注入:设计模式

依赖:程序里需要的某种类型的对象。

依赖注入框架:工程化的框架

注入器Injector:用它的API创建依赖的实例

Provider:怎样创建?(构造函数,工程函数)

Object:组件,模块需要的依赖

依赖性注入进阶=>Angular中依赖注入框架提供父子层次注入型依赖

一、依赖注入

class Id {
  static getInstance(type: string): Id {
    return new Id();
  }
}

class Address {
  constructor(provice, city, district, street) {}
}

class Person {
  id: Id;
  address: Address;
  constructor() {
    this.id = Id.getInstance("idcard");
    this.address = new Address("北京", "背景", "朝阳区", "xx街道");
  }
}

问题:Person需要清楚的知道Address和Id的实现细节。

ID和Address重构后,Person需要知道怎么重构。

项目规模扩大后,集成容易出问题。

class Id {
  static getInstance(type: string): Id {
    return new Id();
  }
}

class Address {
  constructor(provice, city, district, street) {}
}

class Person {
  id: Id;
  address: Address;
  constructor(id: Id, address: Address) {
    this.id = id;
    this.address = address;
  }
}

main(){
  //把构造依赖对象,推到上一级,推调用的地方
  const id = Id.getInstance("idcard");
  const address = new Address("北京", "背景", "朝阳区", "xx街道");
  const person = new Person(id , address);
}

Person已经不知道Id和Address的细节了。

这是最简单的依赖注入。

问题是在main里还是需要知道细节。

思路:一级一级往上推,一直推到入口函数,入口函数来处理所有对象的构造。构造出来后提供给所有依赖的子模块的子类。

问题:入口函数很难维护。所以需要一个依赖注入框架帮助完成。

二、Angular的依赖注入框架

从v5开始,因为速度慢,引入大量代码已弃用,改为Injector.create。

ReflectiveInjector :用于实例化对象和解析依赖关系。import { Component ,ReflectiveInjector } from "@angular/core";resolveAndCreate接收一个provider数组,provider告诉injector应该怎样去构造这个对象。

constructor() {
    //接收一个provider数组
    const injector = ReflectiveInjector.resolveAndCreate([
      {
        provide: Person, useClass:Person
      },
      {
        provide: Address, useFactory: ()=>{
          if(environment.production){
            return new Address("北京", "背景", "朝阳区", "xx街道xx号");
          }else{
            return new Address("西藏", "拉萨", "xx区", "xx街道xx号");
          }
        }
      },
      {
        provide: Id, useFactory:()=>{
          return Id.getInstance('idcard');
        }
      }
    ]);
  }

Injector:

injector相当于main函数,可以拿到所有依赖池子里的东西。

import { Component ,ReflectiveInjector, Inject} from "@angular/core";
import { OverlayContainer } from "@angular/cdk/overlay";
import { Identifiers } from "@angular/compiler";
import { stagger } from "@angular/animations";
import { environment } from 'src/environments/environment';

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.scss"]
})
export class AppComponent {

  constructor(private oc: OverlayContainer) {
    //接收一个provider数组
    const injector = ReflectiveInjector.resolveAndCreate([
      {
        provide: Person, useClass:Person
      },
      {
        provide: Address, useFactory: ()=>{
          if(environment.production){
            return new Address("北京", "背景", "朝阳区", "xx街道xx号");
          }else{
            return new Address("西藏", "拉萨", "xx区", "xx街道xx号");
          }
        }
      },
      {
        provide: Id, useFactory:()=>{
          return Id.getInstance('idcard');
        }
      }
    ]);
    const person = injector.get(Person);
    console.log(JSON.stringify(person));
  }

}

class Id {
  static getInstance(type: string): Id {
    return new Id();
  }
}

class Address {
  provice:string;
  city:string;
  district:string;
  street:string;
  constructor(provice, city, district, street) {
    this.provice=provice;
    this.city=city;
    this.district=district;
    this.street=street;
  }
}

class Person {
  id: Id;
  address: Address;
  constructor(@Inject(Id) id, @Inject(Address )address) {
    this.id = id;
    this.address = address;
  }
}

可以看到控制台打印出person信息。

简写:

 // {
      //   provide: Person, useClass:Person
      // },
      Person, //简写为Person

在Angular框架中,框架做了很多事,在provider数组中注册的东西会自动注册到池子中。

@NgModule({
  imports: [HttpClientModule, SharedModule, AppRoutingModule, BrowserAnimationsModule],
  declarations: [components],
  exports: [components, AppRoutingModule, BrowserAnimationsModule],
  providers:[
    {provide:'BASE_CONFIG',useValue:'http://localhost:3000'}
  ]
})
  constructor( @Inject('BASE_CONFIG') config) {
    console.log(config);  //控制台打印出http://localhost:3000
  }

Angular默认都是单例,如果想要每次注入都是一个新的实例。有两种方法。

一,return的时候return一个方法而不是对象。

{
    provide: Address, useFactory: ()=>{
        return ()=>{
            if(environment.production){
                return new Address("北京", "背景", "朝阳区", "xx街道xx号");
            }else{
                return new Address("西藏", "拉萨", "xx区", "xx街道xx号");
            }
        }
    }
},

二、利用父子Injector。

constructor(private oc: OverlayContainer) {
    //接收一个provider数组
    const injector = ReflectiveInjector.resolveAndCreate([
      Person,
      {
        provide: Address, useFactory: ()=>{
          if(environment.production){
            return new Address("北京", "背景", "朝阳区", "xx街道xx号");
          }else{
            return new Address("西藏", "拉萨", "xx区", "xx街道xx号");
          }
        }
      },
      {
        provide: Id, useFactory:()=>{
          return Id.getInstance('idcard');
        }
      }
    ]);

    const childInjector = injector.resolveAndCreateChild([Person]);

    const person = injector.get(Person);
    console.log(JSON.stringify(person));
    const personFromChild = childInjector.get(Person);
    console.log(person===personFromChild);  //false
  }

子注入器当中没有找到依赖的时候会去父注入器中找

以上就是详解Angular依赖注入的详细内容,更多关于Angular的资料请关注我们其它相关文章!

(0)

相关推荐

  • AngularJS的依赖注入实例分析(使用module和injector)

    本文实例分析了AngularJS的依赖注入.分享给大家供大家参考,具体如下: 依赖注入(DI)的好处不再赘言,使用过spring框架的都知道.AngularJS作为前台js框架,也提供了对DI的支持,这是JavaScript/jQuery不具备的特性.angularjs中与DI相关有angular.module().angular.injector(). $injector.$provide.对于一个DI容器来说,必须具备3个要素:服务的注册.依赖关系的声明.对象的获取.比如spring中,服务

  • 自学实现angularjs依赖注入

    在用angular依赖注入时,感觉很好用,他的出现是 为了"削减计算机程序的耦合问题" ,我怀着敬畏与好奇的心情,轻轻的走进了angular源码,看看他到底是怎么实现的,我也想写个这么牛逼的功能.于是就模仿着写了一个,如果有什么不对,请大家批评指正. 其实刚开始的时候我也不知道怎么下手,源码中有些确实晦涩难懂,到现在我也没有看明白,于是我就静下心想一想,他是怎么用的,如下所示: angular.module(/*省略*/) .factory("xxxService"

  • AngularJS学习第二篇 AngularJS依赖注入

    简介: 首先我们需要理解什么是依赖注入? 控制反转和依赖注入有什么区别? 假定:应用程序A,需要访问外部资源C.这里使用了容器B(是指用来实现 IOC/DI 功能的一个框架程序). A需要访问C B获取C然后返回给A IOC inversion of control 控制反转:站在容器角度.B控制A,由B反向的向A注入C.即容器控制应用程序,由容器反向的向应用程序注入应用程序所需要的外部资源. DI Dependency Injection 依赖注入:站在应用程序的角度.A依赖B获取C,B将C注

  • AngularJS $injector 依赖注入详解

    推断式注入 这种注入方式,需要在保证参数名称与服务名称相同.如果代码要经过压缩等操作,就会导致注入失败. app.controller("myCtrl1", function($scope,hello1,hello2){ $scope.hello = function(){ hello1.hello(); hello2.hello(); } }); 标记式注入 这种注入方式,需要设置一个依赖数组,数组内是依赖的服务名字,在函数参数中,可以随意设置参数名称,但是必须保证顺序的一致性. v

  • Angular.JS学习之依赖注入$injector详析

    前言 在依赖注入(IoC)之前,我们在程序中需要创建一个对象很简单也很直接,就是在代码中new Object即可,有我们自己负责创建.维护.修改和删除,也就是说,我们控制了对象的整个生命周期,直到对象没有被引用,被回收.诚然,当创建或者维护的对象数量较少时,这种做法无可厚非,但是当一个大项目中需要创建大数量级的对象时,仅仅依靠程序员来进行维护所有对象,这是难以做到的,特别是如果想在程序的整个生命周期内复用一些对象,我们需要自己写一个缓存模块对所有对象进行缓存,这加大了复杂度.当然,IoC的好处并

  • 深入理解Angular中的依赖注入

    一.什么是依赖注入 控制反转(IoC) 控制反转的概念最早在2004年由Martin Fowler提出,是针对面向对象设计不断复杂化而提出的一种设计原则,是利用面向对象编程法则来降低应用耦合的设计模式. IoC强调的是对代码引用的控制权由调用方转移到了外部容器,在运行是通过某种方式注入进来,实现了控制反转,这大大降低了程序之间的耦合度.依赖注入是最常用的一种实现IoC的方式,另一种是依赖查找. 依赖注入(Dependency Injection) 当然,按照惯例我们应该举个例子, 哦对,我们主要

  • Angular 4依赖注入学习教程之ValueProvider的使用(七)

    学习目录 Angular 4 依赖注入教程之一 依赖注入简介 Angular 4 依赖注入教程之二 组件服务注入 Angular 4 依赖注入教程之三 ClassProvider的使用 Angular 4 依赖注入教程之四 FactoryProvider的使用 Angular 4 依赖注入教程之五 FactoryProvider配置依赖对象 Angular 4 依赖注入教程之六 Injectable 装饰器 Angular 4 依赖注入教程之七 ValueProvider的使用 Angular

  • angular 服务的单例模式(依赖注入模式下)详解

    angular官方文档单例服务的说明 单例模式就不要说了,懂点设计模式的都懂得,真有不明白的自行百度. (解释下angular的命名,angular就是angular2+,angular1叫angularjs,至于angular2,3,4,5,6只是angular的版本,通称angular,希望小伙伴不要叫错了) 单例模式如何在angular的服务中使用呢,angular的官方文档中有这么一段话: 单例服务 服务在每个注入器的范围内是单例的. 在任何一个注入器中,最多只会有同一个服务的一个实例.

  • Angular 4依赖注入学习教程之InjectToken的使用(八)

    学习目录 Angular 4 依赖注入教程之一 依赖注入简介 Angular 4 依赖注入教程之二 组件服务注入 Angular 4 依赖注入教程之三 ClassProvider的使用 Angular 4 依赖注入教程之四 FactoryProvider的使用 Angular 4 依赖注入教程之五 FactoryProvider配置依赖对象 Angular 4 依赖注入教程之六 Injectable 装饰器 Angular 4 依赖注入教程之七 ValueProvider的使用 Angular

  • 详解Angular依赖注入

    目录 概述 一.依赖注入 二.Angular的依赖注入框架 概述 依赖注入:设计模式 依赖:程序里需要的某种类型的对象. 依赖注入框架:工程化的框架 注入器Injector:用它的API创建依赖的实例 Provider:怎样创建?(构造函数,工程函数) Object:组件,模块需要的依赖 依赖性注入进阶=>Angular中依赖注入框架提供父子层次注入型依赖 一.依赖注入 class Id { static getInstance(type: string): Id { return new Id

  • 详解Spring依赖注入的三种方式以及优缺点

    目录 0.概述 1.属性注入 1.1 优点分析 1.2 缺点分析 2.Setter 注入 优缺点分析 3.构造方法注入 优点分析 总结 0.概述 在 Spring 中实现依赖注入的常见方式有以下 3 种: 属性注入(Field Injection): Setter 注入(Setter Injection): 构造方法注入(Constructor Injection). 它们的具体使用和优缺点分析如下. 1.属性注入 属性注入是我们最熟悉,也是日常开发中使用最多的一种注入方式,它的实现代码如下:

  • 详解Spring依赖注入:@Autowired,@Resource和@Inject区别与实现原理

    一.spring依赖注入使用方式 @Autowired是spring框架提供的实现依赖注入的注解,主要支持在set方法,field,构造函数中完成bean注入,注入方式为通过类型查找bean,即byType的,如果存在多个同一类型的bean,则使用@Qualifier来指定注入哪个beanName的bean. 与JDK的@Resource的区别:@Resource是基于bean的名字,即beanName,来从spring的IOC容器查找bean注入的,而@Autowried是基于类型byType

  • 详解Angular动态组件

    使用场景 我们先明确下动态组件的使用场景,在代码运行时要动态加载组件,换成普通人话,代码需要根据具体情况(比如用户的操作,向后台请求结果)确定在某些地方加载某些组件,这些组件不是静态的(不是固定的). 官网的举例就是,构建动态广告条,广告组件不断会推出新的,再用只支持静态组件结构的模板显然是不现实的. 再举一个常见的例子,动态弹出框,弹出的组件是不确定的.不断更新的,这里那里弹出个购买框,那那那又需要弹出样式选择框,静态组件结构模板是不能满足群众日渐增长的需求. 怎么实现 然后我们来找个把手,看

  • 详解Angular组件生命周期(一)

    概述 组件声明周期以及angular的变化发现机制 红色方法只执行一次. 变更检测执行的绿色方法和和组件初始化阶段执行的绿色方法是一个方法. 总共9个方法. 每个钩子都是@angular/core库里定义的接口. import { Component, OnInit } from '@angular/core'; @Component({ selector: 'app-life', templateUrl: './life.component.html', styleUrls: ['./life

  • 详解Angular组件之中间人模式

    一.中间人模式 该组件树中除了组件1以外,每个组件都有一个父组件可以扮演中间人的角色.顶级的中间人是组件1,它可以使组件2,组件3,组件6之间互相通讯.依次类推,组件2是组件4和组件5的中间人.组件3是组件7和组件8的中间人. 中间人负责从一个组件接收数据并将其传递给另一个组件. 二.例子 股票报价组件为例,假设交易员在监看着报价组件的价格,当股票价格达到某一个值的时候,交易员会点一个购买按钮,来购买股票.问题:报价组件并不知道应该如何下单来买股票,它只是用来监控股票价格的.所以报价组件在这时应

  • 详解Angular中$cacheFactory缓存的使用

    最近在学习使用angular,慢慢从jquery ui转型到用ng开发,发现了很多不同点,继续学习吧: 首先创建一个服务,以便在项目中的controller中引用,服务有几种存在形式,factory();service();constant();value();provider();其中provider是最基础的,其他服务都是基于这个写的,具体区别这里就不展开了,大家可以看看源码:服务是各个controller之间通话的重要形式,在实际项目中会用的很多,下面是代码: angular.module

  • 详解maven依赖冲突以及解决方法

    什么是依赖冲突 依赖冲突是指项目依赖的某一个jar包,有多个不同的版本,因而造成类包版本冲突 依赖冲突的原因 依赖冲突很经常是类包之间的间接依赖引起的.每个显式声明的类包都会依赖于一些其它的隐式类包,这些隐式的类包会被maven间接引入进来,从而造成类包冲突 如何解决依赖冲突 首先查看产生依赖冲突的类jar,其次找出我们不想要的依赖类jar,手工将其排除在外就可以了.具体执行步骤如下 1.查看依赖冲突 a.通过dependency:tree是命令来检查版本冲突 mvn -Dverbose dep

  • 详解Angular父子组件通讯

    概述 Angular组件间通讯 组件树,1号是根组件AppComponent. 组件之间松耦合,组件之间知道的越少越好. 组件4里面点击按钮,触发组件5的初始化逻辑. 传统做法:在按钮4的点击事件里调用组件5的方法.紧密耦合. Angular:在组件4根本不知道组件5存在的情况下实现. 使用松耦合的方式在组件之间传递数据开发出高重用性的组件. 使用输入输出属性在父子关系的组件之间传递数据. 一.输入输出属性概述 组件设计成黑盒模型,用输入属性声明从外部世界接收什么东西.不需要知道这些东西从哪里来

  • 详解Angular结构型指令模块和样式

    一,结构型指令 *是一个语法糖,<a *ngIf="user.login">退出</a>相当于 <ng-template [ngIf]="user.login"> <a>退出</a> </ng-template> 避免了写ng-template. <ng-template [ngIf]="item.reminder"> <mat-icon > alar

随机推荐