博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Angular 依赖注入
阅读量:6324 次
发布时间:2019-06-22

本文共 3120 字,大约阅读时间需要 10 分钟。

问题描述

初学Angular,可能对一堆注解有些懵。

我们一起通过实例来探讨Angular的依赖注入。

一路尝试

@Injectable

一个命令建的StockService,一个手动建的TestService

@Injectable({    providedIn: 'root'})export class StockService {    constructor(private testService: TestService) {    }}
export class TestService {    constructor() {    }}

TestService未加@Injectable注解,只是一个普通的TypeScript类。

当前台组件中用到StockService时,Angular为我们构造StockService,构造函数中依赖TestService,然后Angular去构造TestService

clipboard.png

Uncaught (in promise): Error: StaticInjectorError(AppModule)[TestService]: StaticInjectorError(Platform: core)[TestService]: NullInjectorError: No provider for TestService!

然后发现控制台报错,无法提供TestService,因为它没有被Angular管理。

import {Injectable} from '@angular/core';@Injectable()export class TestService {    constructor() {    }}

加上@Injectable,将该类交给Augular管理。

clipboard.png

无效,仍然报错。发现只交给Angular托管是不行的,我们还需要声明提供器。

提供器

需要提供器告诉Angular如何注入相关对象。

@NgModule({    declarations: [],    imports: [],    providers: [TestService],    bootstrap: [AppComponent]})export class AppModule {}

clipboard.png

AppModuleproviders数组中声明TestService提供器。

按类型提供,所以上面的声明与下面的代码是等价的。

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

标记在AppModule上,表示该TestService的注入是应用在该模块上的。在该模块中,TestService是单例的。

{ provide: TestService, useClass: TestService },表示当需要注入TestService类型的对象时,使用TestService类构造出的对象进行注入。

Angular中,为什么@Component@Pipe里能用构造函数注入@Injectable呢?答案与Spring一致,为什么@Controller@Service里能Autowired呢?思想相同。

作用域

@NgModule({    providers: [TestService]})export class AppModule {}@Component({    providers: [{ provide: TestService, useClass: AnotherTestService }]})export class StockComponent {    constructor(private testService: TestService) {    }}

声明一个模块级的与一个组件级的提供器,表示在本模块或本组件中应该注入什么。

就像如上代码,声明在整个AppModule模块中,注入的TestServiceTestService类实例化的。

但是具体到组件,StockComponent,虽然声明整个模块都使用TestService,但是有时不符合需求,所以在此组件中使用AnotherTestService注入。

就像Spring中的@Primary@Qualifier一样。

值提供与工厂方法

通过useValue的值提供,可以定义一些常量,又是枚举的思想,我们使用引用,而不是用常量。

{ provide: domain, useValue: 'www.mengyunzhi.com' }

除了值提供还有工厂方法,当Angular默认的实例化对象无法满足我们的要求时,我们要写自己的工厂函数生成我们的对象实例。

但是注意:虽然该方法叫工厂方法,但是该方法只在第一次用到该对象时执行一次,以后再需要用的还是之前构造出来的对象。

虽然叫工厂方法,但是还是单例的。

{ provide: ProductService, useFactory: () => { 返回一个对象实例 } }

摇树优化

现在如果用ng生成的Angular服务,标准的写法是providedIn: 'root'

粗略学习了一下,摇树优化就是按需加载,减小我们的包体积,缩短应用的加载时间。

@Injectable({    providedIn: 'root'})

只要在服务本身的@Injectable()装饰器中指定,而不是在依赖该服务的NgModule或组件的元数据中指定,你就可以制作一个可摇树优化的提供商。

要想覆盖可摇树优化的提供商,请使用其它提供商来配置指定的NgModule或组件的注入器,只要使用@NgModule()@Component()装饰器中的providers: []数组就可以了。

循环依赖

通过上面的学习,我们知道了Angular中的依赖注入是通过构造函数的参数注入来实现的。

但是只要是通过构造函数实现的IOC容器就会有问题,就像Spring中一样,如果循环依赖了怎么解决呢?

clipboard.png

@Injectable({    providedIn: 'root'})export class StockService {    constructor(private testService: TestService) {    }}
@Injectable({    providedIn: 'root'})export class TestService {    constructor(private stockService: StockService) {    }}

clipboard.png

Circular dependency detected:src/app/service/stock.service.ts -> src/app/service/test.service.ts -> src/app/service/stock.service.tsCircular dependency detected:src/app/service/test.service.ts -> src/app/service/stock.service.ts -> src/app/service/test.service.ts

Spring一样,如果循环了,因为是使用构造函数注入,所以一个对象都构造不出来,无法解决。开发时应避免循环依赖。

总结

万物相通。

Hello, Angular!

转载地址:http://xovaa.baihongyu.com/

你可能感兴趣的文章
c#用EPPLUS操作excel
查看>>
对于非法输入的处理
查看>>
访问修饰符的含义分析
查看>>
Salesforce
查看>>
开始学java了!
查看>>
【转】C# GET 和 SET作用
查看>>
网站面试题
查看>>
C# 取两个集合的交集\并集\差集
查看>>
EJB的生命周期,及如何管理事务?
查看>>
怎么去用java经典递归算法?
查看>>
tf.Variable
查看>>
GBDT-梯度提升树
查看>>
for 穷举
查看>>
单例模式的使用场景
查看>>
SftpUtil FTP文件上传
查看>>
UVA10815 Andy's First Dictionary
查看>>
Ext程序规划入门
查看>>
springboot集成swagger文档
查看>>
box-shadow
查看>>
实验3密码破解技术
查看>>