0

0

什么是依赖注入?在Angular中怎么实现?

青灯夜游

青灯夜游

发布时间:2022-02-02 09:00:30

|

2370人浏览过

|

来源于掘金社区

转载

本篇文章带大家了解一下依赖注入,介绍一下依赖注入解决的问题和它原生的写法是,并聊聊angular的依赖注入框架,希望对大家有所帮助!

什么是依赖注入?在Angular中怎么实现?

最近在Angular项目中经常能碰到依赖注入这个关键词,但是始终不理解它是怎么实现的,在Angular的官网上也只有关于它的使用,详细点的原理并没有说明,所以就下来我们就从原生的写法来讲解一下,依赖注入是用来解决什么问题的,他用js应该怎么去表现。【相关教程推荐:《angular教程》】

依赖注入是什么

依赖注入简称DI,是面向对象编程中的一种设计原则,用来减少代码之间的耦合度。

我们先来看一段代码

class Video{
    constructor(url){}
}

class Note{
    video: Video
    constructor(){
        this.video = new Video("https://aaaaa.mp4")
    }
    
    getScreenshot(){
        this.video.getScreenshot()
    }
}

const note = new Note()
note.getScreenshot()

假设我们用一个视频类,它其中有一个方法 getScreenshot 获取截图,在实例化视频类的时候,需要传入一个视频 url 这样的参数。现在有一个笔记类,它需要去调用视频类下的截图方法,那么我们就可以说,笔记类是依赖于视频类的。所以在笔记类的内部,我们就需要去实例化视频类,这样才能在笔记类中获取视频类的实例对象,并且调用它里面的截图方法。

上面代码的耦合度过高,并不推荐使用,比方说如果Video的视频地址换了一个,那么在Note中就需要去改变传入的视频url,这样假设要是有更多的类依赖于视频类,那么一旦做出更改,那么所有地方都要跟着改变,非常的不方便。

接下来利用依赖注入解决上面的问题:

class Note{
    video: Video
    constructor(video: Video){
        this.video = Video;
    }
}

const video = new Video("https://aaaaa.mp4")
const note = new Note(video)

我们在类的外部去实例化视频类,并且通过参数传递的方式把实例传递给了笔记类,通过这样的方式就能够成功解决耦合度过高的问题,我们把通过参数传递实例的这种方式称为:注入。

优点

通过依赖注入降低了代码之间的耦合度,增加了代码的可维护性。视频类中的代码更改也不会去影响到笔记类了。

Angular的DI框架

在上述实现的过程当中,还是有着一个不是特别理想的地方,就是我们需要在类的外部去实例化视频类,虽然只有这一处,但是我们还是希望视频类的内部再怎么更改,都不会影响外部代码。

在 Angular 提供的 DI 框架中,我们就不需要自己去做视频类的实例化操作,它将实现依赖注入的过程隐藏了,对于开发者来说,只需要使用很简单的代码就可以使用复杂的依赖注入功能。

在 Angular 的 DI 有四个核心的概念:

  • Dependency:组件要依赖的实例对象,服务实例对象

    TP-COUPON 导购系统 免费版
    TP-COUPON 导购系统 免费版

    自从百度屏蔽淘宝客网站、淘宝抛弃淘宝客之后,个人站长集体陷入了恐慌之中。此时,什么值得买网的异军突起引起了广大个人站长的极大关注。做一个什么值得买一样的导购网站成了众多个人站长的一致心愿! TP-COUPON 导购系统 即是让个人站长实现此心愿的绝佳选择! 欢迎个人站长选用。V1.1版 更新记录:1.修正请求时查询淘宝店铺错误的bug2.删除一些无用的代码

    下载
  • Token:获取服务实例对象的标识,在Angular会维护很多的实例对象,在我们需要获取的时候,就需要通过标识去获取

  • Injector:注入器,负责创建维护服务类的实例对象,并向组件中注入服务实例对象,通过参数的方式传递给各个组件

  • Procider:对象,用于配置注入器,指定创建服务实例对象的服务类和获取实例对象的标识

Injector注入器

我们先通过Angular提供的基本语法来创建一个注入器

1、创建注入器

import { ReflectiveInjector } from "@angular/core"
//服务类
class Video{}
//创建注入器并传入服务类
const injector = ReflectiveInjector.resolveAndCreate([ Video ])

引入ReflectiveInjector其中resolveAndCreate方法用于创建注入器,它接收一个数组,数组中就是需要创建实例对象的类,这个方法会返回一个注入器 2. 获取注入器中的服务类实例对象

const video = injector.get(Video)

在injector下有一个get方法,用于传入标识并且获取实例对象,默认标识就是服务类的名称也就是Video

这样我们就能够获取到Video的实例对象了,Angular给我们提供的这套DI框架使得我们不需要去手动的实例化某一个类来获得它的实例对象,它会来帮我们完成。

2、服务的实例对象为单例模式,注入器在创建服务实例后悔对其进行缓存

const video1 = injector.get(Video)
const video2 = injector.get(Video)

console.log(video1 === video1)//true

也就是说,无论通过框架获取多少次实例对象,他返回的都是同一个实例对象

3、但是我们可以通过创建多个注入器,不同的注入器返回的同一个服务实例化的对象不是同一个

const injector1 = ReflectiveInjector.resolveAndCreate([ Video ])
const injector2 = ReflectiveInjector.resolveAndCreate([ Video ])

const video1 = injector1.get(Video)
const video2 = injector2.get(Video)

console.log(video1 === video1)//false

4、注入器上面存在一个创建子级注入器的方法为 resolveAndCreateChild,这个方法会创建一个子级注入器,父级注入器和子级注入器之间的关系类似于js的作用域链,当前注入器查找不到就会去父级注入器查找,比如:

const injector = ReflectiveInjector.resolveAndCreate([ Video ])
const injectorChild = injector.resolveAndCreateChild([])

const video1 = injector.get(Video)
const video2 = injectorChild.get(Video)

console.log(video1 === video1)//true

像上面这段代码,我们在创建子级注入器的时候,不传递参数,但是在子级注入器实例化的时候,由于自身不存在 Video 这个服务,它就会去父级查找,当然,就找到了父级的 Video 这个服务并且实例化,所以后面的两个实例化对象相等

总结

本文介绍了依赖注入解决的问题和它原生的写法是什么用的,并且介绍了Angular提供给我们的DI框架,用它提供给我们的简单api实现了实例化的过程,并且讲解了注入器,也是会分层级的,能提供给我们更好地一个项目设计方式。之后有机会再来讲解一下provider以及更多的扩展。

更多编程相关知识,请访问:编程视频!!

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Golang 测试体系与代码质量保障:工程级可靠性建设
Golang 测试体系与代码质量保障:工程级可靠性建设

Go语言测试体系与代码质量保障聚焦于构建工程级可靠性系统。本专题深入解析Go的测试工具链(如go test)、单元测试、集成测试及端到端测试实践,结合代码覆盖率分析、静态代码扫描(如go vet)和动态分析工具,建立全链路质量监控机制。通过自动化测试框架、持续集成(CI)流水线配置及代码审查规范,实现测试用例管理、缺陷追踪与质量门禁控制,确保代码健壮性与可维护性,为高可靠性工程系统提供质量保障。

48

2026.02.28

Golang 工程化架构设计:可维护与可演进系统构建
Golang 工程化架构设计:可维护与可演进系统构建

Go语言工程化架构设计专注于构建高可维护性、可演进的企业级系统。本专题深入探讨Go项目的目录结构设计、模块划分、依赖管理等核心架构原则,涵盖微服务架构、领域驱动设计(DDD)在Go中的实践应用。通过实战案例解析接口抽象、错误处理、配置管理、日志监控等关键工程化技术,帮助开发者掌握构建稳定、可扩展Go应用的最佳实践方法。

44

2026.02.28

Golang 性能分析与运行时机制:构建高性能程序
Golang 性能分析与运行时机制:构建高性能程序

Go语言以其高效的并发模型和优异的性能表现广泛应用于高并发、高性能场景。其运行时机制包括 Goroutine 调度、内存管理、垃圾回收等方面,深入理解这些机制有助于编写更高效稳定的程序。本专题将系统讲解 Golang 的性能分析工具使用、常见性能瓶颈定位及优化策略,并结合实际案例剖析 Go 程序的运行时行为,帮助开发者掌握构建高性能应用的关键技能。

37

2026.02.28

Golang 并发编程模型与工程实践:从语言特性到系统性能
Golang 并发编程模型与工程实践:从语言特性到系统性能

本专题系统讲解 Golang 并发编程模型,从语言级特性出发,深入理解 goroutine、channel 与调度机制。结合工程实践,分析并发设计模式、性能瓶颈与资源控制策略,帮助将并发能力有效转化为稳定、可扩展的系统性能优势。

22

2026.02.27

Golang 高级特性与最佳实践:提升代码艺术
Golang 高级特性与最佳实践:提升代码艺术

本专题深入剖析 Golang 的高级特性与工程级最佳实践,涵盖并发模型、内存管理、接口设计与错误处理策略。通过真实场景与代码对比,引导从“可运行”走向“高质量”,帮助构建高性能、可扩展、易维护的优雅 Go 代码体系。

19

2026.02.27

Golang 测试与调试专题:确保代码可靠性
Golang 测试与调试专题:确保代码可靠性

本专题聚焦 Golang 的测试与调试体系,系统讲解单元测试、表驱动测试、基准测试与覆盖率分析方法,并深入剖析调试工具与常见问题定位思路。通过实践示例,引导建立可验证、可回归的工程习惯,从而持续提升代码可靠性与可维护性。

3

2026.02.27

漫蛙app官网链接入口
漫蛙app官网链接入口

漫蛙App官网提供多条稳定入口,包括 https://manwa.me、https

268

2026.02.27

deepseek在线提问
deepseek在线提问

本合集汇总了DeepSeek在线提问技巧与免登录使用入口,助你快速上手AI对话、写作、分析等功能。阅读专题下面的文章了解更多详细内容。

51

2026.02.27

AO3官网直接进入
AO3官网直接进入

AO3官网最新入口合集,汇总2026年可用官方及镜像链接,助你快速稳定访问Archive of Our Own平台。阅读专题下面的文章了解更多详细内容。

430

2026.02.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Vue.js:纪录片
Vue.js:纪录片

共1课时 | 0.2万人学习

Angular js入门篇
Angular js入门篇

共17课时 | 3.5万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号