Angular4学习笔记(四)- 依赖注入
来源:互联网 发布:解数学题用什么软件 编辑:程序博客网 时间:2024/05/16 10:22
概念
依赖注入是一种设计思想,并不是某一类语言所特有的,因此可以参考开涛大神关于学习Java语言的Spring框架
时对其的解释:
DI—Dependency Injection,即“依赖注入”:是组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。
理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:
- 谁依赖于谁:当然是应用程序依赖于IoC容器;
- 为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;
- 谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象;
- 注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。
IoC和DI由什么关系呢?其实它们是同一个概念的不同角度描述,由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),所以2004年大师级人物Martin Fowler又给出了一个新的名字:“依赖注入”,相对IoC 而言,“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”。 1
Angular中的依赖注入
Angular中可以在app.module.ts
中进行全局声明,也可以在组件内部根据特定需求实现特定声明。
声明是通过属性providers
实现的,顾名思义,它是一个对象提供者,复数形式表名其为数组形式。且子类型为Provide
,它位于@angular/core
中,实现如下:
export interface TypeProvider extends Type<any> {}export interface ValueProvider { provide: any; useValue: any; multi?: boolean;}export interface ClassProvider { provide: any; useClass: Type<any>; multi?: boolean;}export interface ExistingProvider { provide: any; useExisting: any; multi?: boolean;}export interface FactoryProvider { provide: any; useFactory: Function; deps?: any[]; multi?: boolean;}export declare type Provider = TypeProvider | ValueProvider | ClassProvider | ExistingProvider | FactoryProvider | any[];
可以看到,Provider
共有5个明确的子类,也决定了其使用方式的数量。由于全局声明和组件内部声明的方式差别不大,可见的区别是在app.module.ts
中属性providers
是在模块注解@NgModule
中声明而组件中是通过注解@Component
声明。因此实现方式不对全局和组件加以区分。
由于是初学,此处仅列举常用的几种方式:useClass
、useFactory
和useValue
。
useClass
providers: [{provide: DefaultBookService, useClass: DefaultBookService}]
其中provide
定义了token
,而useClass
则指明了使用的类,此处由于token
和实现类相同,均为DefaultBookService
因此可以简写为
providers: [DefaultBookService]
useFactory
providers: [{ provide: DefaultBookService, useFactory: () => { const rdm = Math.random() < 0.5; if (rdm) { return new DefaultBookService(); } else { return new HuaZhangBookService(); } }
HuaZhangBookService
是DefaulteBookService
的一个子类。根据情况返回所需注入的对象。
如果通过依赖注入的对象同时依赖另一个通过依赖注入的对象应如何实现呢?比如DefaultBookService
,它的构造函数为:
constructor(public logger: LoggerService) { }
而LoggerService也是通过依赖注入-即不需要自己手工new LoggerService()
-时应该怎么办?在类FactoryProvider
中提供了一个名叫deps
的参数,它可以帮助我们实现依赖对象的引用。用法如下:
providers: [{ provide: DefaultBookService, useFactory: (logger: LoggerService) => { const rdm = Math.random() < 0.5; if (rdm) { return new DefaultBookService(logger); } else { return new HuaZhangBookService(logger); } }, deps: [LoggerService] }, LoggerService]
deps
是一个任意类型的数组,为什么呢,因为类的参数不会只有一个,当构造方法中有多个参数时,可同时依赖多个不同类型的对象。
useValue
基本用法: {provide: 'IS_DEV_ENV', useValue: Math.random() < 0.5}
扩展用法:
providers: [{ provide: DefaultBookService, useFactory: (logger: LoggerService, isDev) => { if (isDev) { return new DefaultBookService(logger); } else { return new HuaZhangBookService(logger); } }, deps: [LoggerService, 'IS_DEV_ENV'] }, LoggerService, {provide: 'IS_DEV_ENV', useValue: Math.random() < 0.5} ]
可以看到,在useFactory
的箭头表达式中有两个参数,他们依次对应deps
中的token
,即isDev对应token为IS_DEV_ENV
的对象,而它正是使用了本小节中所涉及的useValue
形式,它返回一个boolean
对象。
另外需要注意的是,token
不止能指定特定的类,也可以指定特定的值。
multi
参考
- Angular 2 Multi Providers。
- multi的用处是什么?
其他
- 以上我们简单介绍了几种Angular实现依赖注入的方式,但是还需要提供使用它的条件,在Angular中,只有当组件或者服务被注解
@Injectable
或其子类如@Component
修饰后,才可使用,建议无论是否使用依赖注入,都使用@Injectable
修饰。 - 可以通过构造方法的参数来放置通过依赖生成的对象:
constructor(private bookService: DefaultBookService) { }this.bookService
来调用DefaultBookService
中的方法了。 - 通过依赖注入传入的对象,可以通过
Injector
来进行访问,它位于@angular/core
包中,因此上面的构造方法可以这样声明constructor(private injector: Injector) { }
,
通过this.injector.get(DefaultBookService)
来获取DefaultBookService
对象并调用其中的方法,但不建议这样做,因为不如直接传入所需对象来的明确。 - 在
app.module.ts
中使用useFactory
并且使用箭头表达式来实现时,注册的组件会报错,至今无解,相关问题已发至segmentFault,哪位大神如果知道,烦请告诉,跪谢。 - 关于
Token
的学习可以参考Angular 4 依赖注入教程之八 InjectToken的使用
- 如果想要更加深入的了解IoC和DI,请参考大师级人物Martin Fowler的一篇经典文章《Inversion of Control Containers and the Dependency Injection pattern》,原文地址:http://www.martinfowler.com/articles/injection.html。 ↩
- Angular4学习笔记(四)- 依赖注入
- Angular4学习笔记(四)
- Angular4学习笔记(四):service
- Angular4中的依赖注入
- Angularjs学习笔记(四)模块化与依赖注入
- EJB3.0学习笔记之四 依赖注入(dependency injection)
- angular4学习笔记(一)
- Spring学习笔记(1)---依赖注入
- Spring学习笔记(8)-----------依赖注入
- EJB学习笔记七(依赖注入)
- Spring学习笔记(三)依赖注入
- EJB学习笔记_10_依赖注入(beanname注入)
- angular4基础之服务与依赖注入
- Angular4-在线竞拍应用-依赖注入
- Angular4 第四章 依赖注入基本概念
- Angular4 第四章 依赖注入实战
- Spring 学习笔记 ----依赖注入
- [学习笔记]Spring依赖注入
- Android viewpager+photoview的使用
- 知情人士:乐视与阿斯顿马丁合作中止,或因乐视缺钱
- HDOJ1248(完全背包)
- 双lazytag线段树板子
- Trim a Binary Search Tree(leetcode)
- Angular4学习笔记(四)- 依赖注入
- JavaScript 数组
- Semi-supervised Segmentation of Optic Cup in Retinal Fundus
- 数字信号处理学习:基于CIC滤波器的正交检波
- FFMPEG录屏软件开发之YUV AAC合成MP4
- 183. Customers Who Never Order
- 集合类(一)
- python 关于集合,还有浅拷贝和深拷贝的问题
- 腾讯云赋能“互联网+”,中国制造业迎智能化新机遇